索引通常能够极大的提高查询的效率。在系统中使用查询时,应该考虑建立相关的索引。
索引是一种数据结构,他搜集一个集合中文档特定字段的值。MongoDB的查询优化器能够
使用这种数据结构来快速的对集合(collection)中的文档(collection)进行寻找和排序,
准确来说,这些索引是通过B-Tree索引来实现的。
1.创建简单索引
数据准备index.js,创建books文档并插入200000条数据,如下:
for(var i=0;i<200000;i++){
db.books.insert({number:i,name:i+"book"})
}
1.先检验一下查询性能
var start = new Date()
db.books.find({number:65871})
var end = new Date()
end - start
2.为number 创建索引
db.books.ensureIndex({number:1})
3.再执行第一部的代码可以看出有数量级的性能提升
2.索引使用需要注意的地方
1.创建索引的时候注意1是正序创建索引-1是倒序创建索引
2.索引的创建在提高查询性能的同事会影响插入的性能对于经常查询少插入的文档可以考虑用索引
3.符合索引要注意索引的先后顺序
4.每个键全建立索引不一定就能提高性能呢索引不是万能的
5.在做排序工作的时候如果是超大数据量也可以考虑加上索引用来提高排序的性能
3.创建索引同时指定索引的名字
db.books.ensureIndex({name:-1},{name:”bookname”})
4.唯一索引
4.1如何解决文档books不能插入重复的数值
建立唯一索引
db.books.ensureIndex({name:-1},{unique:true})
试验
db.books .insert({name:”1book”})
5.剔除重复值
5.1如果建议唯一索引之前已经有重复数值如何处理
db.books.ensureIndex({name:-1},{unique:true,dropDups:true})
6.Hint
6.1如何强制查询使用指定的索引呢?
db.books.find({name:"1book",number:1}).hint({name:-1})
指定索引必须是已经创建了的索引
7.Expain
7.1如何详细查看本次查询使用那个索引和查询数据的状态信息
db.books.find({name:"1book"}).explain()
返回结果,如下所示:
> db.books.find({name:"1book"}).explain()
{
"cursor" : "BtreeCursor name_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"name" : [
[
"1book",
"1book"
]
]
},
"server" : "PC-20110917QHJT:27017"
}
"cursor" : "BtreeCursor name_1" 使用索引
"nscanned" : 1 查到几个文档
"millis" : 0 查询时间,0是很不错的性能
二、索引管理
8、system.indexes
8.1、在shell中,查看数据库已经建立的索引。如下:
db.system.indexes.find()
db.system.namespaces.find()
9、后台执行
9.1、执行创建索引的过程会暂时锁表问题,如何解决?
为了不影响查询,我们可以让索引的创建过程在后台执行。
db.books.ensureIndex({number:1},{true})
10、删除索引
10.1、批量和精确删除索引
db.runCommand({dropIndexes:"books",index:"name_1"}) 精确删除索引
db.runCommand({dropIndexes:"books",index:"*"}) 批量删除索引
三、空间索引
11、mongoDB提供强大的空间索引,可以查询出一定范围的地理坐标。示例如下:
准备数据map.txt,如下图:
var map = [{
"gis" : {
"x" : 185,
"y" : 150
}
},{
"gis" : {
"x" : 70,
"y" : 180
}
},{
"gis" : {
"x" : 75,
"y" : 180
}
},{
"gis" : {
"x" : 185,
"y" : 185
}
},{
"gis" : {
"x" : 65,
"y" : 185
}
},{
"gis" : {
"x" : 50,
"y" : 50
}
},{
"gis" : {
"x" : 50,
"y" : 50
}
},{
"gis" : {
"x" : 60,
"y" : 55
}
},{
"gis" : {
"x" : 65,
"y" : 80
}
},{
"gis" : {
"x" : 55,
"y" : 80
}
},{
"gis" : {
"x" : 0,
"y" : 0
}
},{
"gis" : {
"x" : 0,
"y" : 200
}
},{
"gis" : {
"x" : 200,
"y" : 0
}
},{
"gis" : {
"x" : 200,
"y" : 200
}
}]
for(var i = 0;i<map.length;i++){
db.map.insert(map[i])
}
首先,添加2D索引(默认会建立一个[-180,180]之间的2D索引)
db.map.ensureIndex({"gis":"2d"},{min:-1,max:201})
11.1、查询出距离点(70,180)最近的3个点
db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3)//$near操作符表示中心点;如果没有指定limit,其默认值为100。
11.2、查询以点(50,50)和(190,190)为对角线的正方形中的所有点
var box=[[50,50],[190,190]];//定义一个矩形区域
db.map.find({"gis":{"$within":{"$box":box}}},{gis:1,_id:0})//$box 矩形查找
11.3、查询出以圆心为(55,80),半径为50,规则下的圆心面积中的点
var center=[55,80];//定义中心点
var radius=50;//定义半径
db.map.find({"gis":{"$within":{"$center":[center,radius]}}});//$center 圆形查找(注意这里是数组传递)