一、索引详讲
1、创建简单索引
准备数据,创建books文档并插入200000条数据,如下:
for(var i=0;i<200000;i++){
db.books.insert({number:i,name:i+"book"})
}
1.1、先检验一下查询性能
var start=new Date()
db.books.find({number:65888})
var end=new Date()
end-start
2.2、为number创建索引
db.books.ensureIndex({number:1})
3.3、再执行第一次查询的代码,可以看出有数量级的性能提升,大概10倍以上。
2、索引使用需要注意的地方
2.1、创建索引的时候,注意1是正序创建索引,-1是倒序创建索引。
2.2、索引的创建,在提高查询性能的同时,会影响增删改的性能;
对于经常查询少插入的文档可以考虑用索引。
2.3、符合索引要注意索引的先后顺序。
2.4、每个键全建立索引不一定就能提高性能,索引不是万能的。
2.5、在做排序工作的时候,如果是超大数据量,也可以考虑加上索引,用来提高排序的性能。
3、索引的名称
3.1、用VUE查看索引名称,如下图:
3.2、创建索引同事指定索引的名字
db.books.ensureIndex({name:-1},{name:"bookname"})
4、唯一索引
4.1、如何解决文档books不能插入重复的数值
建立唯一索引
db.books.ensureIndex({name:1},{unique:true})
测试
db.books.insert({name:"1book"})
错误信息:E11000 duplicate key error index: foorbar.books.$name_1 dup key: { : "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})
指定索引必须是已经创建好的索引(包括顺序),否则会报如下错误:
error: { "$err" : "bad hint", "code" : 10113 }
7、explain
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,如下图:
首先,添加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 圆形查找(注意这里是数组传递)