MongoDB索引介绍
数据准备:向MongoDB数据库插入20万条数据,执行如下代码:
for(var i = 0 ; i<200000 ;i++){
db.books.insert({number:i,name:i+"book"})
}
- 创建简单索引
先看一下现在的查询性能:
var startTime = new Date()
db.books.find({number:65871})
var endTime = new Date()
endTime - startTime
没有索引,一般查询时间在80-90ms之间。下面创建一个索引:
db.books.ensureIndex({number:1})
再来看一下查询时间,同样执行上面的查询语句。
时间上来看,添加索引后查询时间明显缩短,缩短到5-10ms左右,比以前缩短了很多倍,由此可见,适当的索引对于查询效率还是有很大的提升的。
下面我们来看看使用索引需要注意的地方。
2. 索引使用需要注意的地方
1).创建索引的时候注意1是正序创建索引,-1是倒序创建索引,具体使用取决于具体需求。
2).索引的创建在提高查询性能的同时会影响插入的性能。
因此对于经常查询少插入的文档可以考虑用索引,而对于经常插入文档较少查询的集合反而添加索引不一定有效率提升。
3).复合索引要注意索引的先后顺序
4).每个键全建立索引不一定就能提高性能
索引不是万能的,适当的索引可以提高性能,但是并不是每个键都要建立索引,这样不一定能够提高性能。
5).在做排序工作的时候,如果是超大数据量也可以考虑加上索引
索引用来提高排序的性能
3 . 索引的名称
之前已经创建了number上的索引,查看一下名称:
之前创建的索引名称为:number_1,这个number是索引键,1是索引方式:正序创建索引
4 . 创建索引同时指定索引的名字
db.books.ensureIndex({name:-1},{name:"bookname"})
5 . 唯一索引
索引有很多种,唯一索引是保证建立唯一索引的键值不能重复,如_id就有唯一索引,与普通唯一索引不同的是,_id上的唯一索引是不能删除的,而普通索引可以。下面来建立唯一索引:
db.books.ensureIndex({name:-1},{unique:true})
下面插入重复数据:
db.books.insert({name:"0book"})
6 . 剔除重复值
如果创建唯一索引时,该键已经包含重复数据,那么应该怎么办?
在MongoDB 2.7.5以前正常使用,在MongDB 2.7.5之后已经被移除,官方Manual描述:
Remove dropDups Option dropDups option is no longer available for createIndex(), ensureIndex(),and createIndexes.
7 . 如何强制查询使用指定的索引呢?使用Hint
db.books.find({name:"1book",number:1}).hint({name:-1})
指定索引必须是已经创建了的索引
MongoDB索引管理
- system.indexes
在MongoDB shell中,即命令行模式下,输入:
show collections
结果如下:
其中system.indexes即保存着索引的信息,我们在shell查看数据库已经建立的索引
db.system.indexes.find()
db.system.namespaces.find()
结果如图:
2 . 执行创建索引的过程会暂时锁表问题如何解决?
为了不影响查询我们可以叫索引的创建过程在后台进行,如:
db.books.ensureIndex({name:-1},{background:true})
3 . 删除索引
批量和精确删除索引
精确删除索引:
删除前:
db.runCommand({dropIndexes:"books",index:"name_1"})
删除后:
批量删除:
db.runCommand({dropIndexes:"books",index:"*"})
删除后:
剩余一个_id的索引是无法删除的。
MongoDB空间索引
- mongoDB提供强大的空间索引可以查询出一定范围的地理坐标.看例子,
准备数据:
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])
}
该数据是地图上的一些点的坐标,如图:
下面来看具体使用:
1.查询出距离点(70,180)最近的3个点
1)添加2D索引
db.map.ensureIndex({"gis":"2d"},{min:-1,max:201})
默认会建立一个[-180,180]之间的2D索引
2)查询点(70,180)最近的3个点
db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3)
2.查询以点(50,50)和点(190,190)为对角线的正方形中的所有的点
db.map.find({gis:{"$within":{$box:[[50,50],[190,190]]}}},{_id:0,gis:1})
3.查询出以圆心为(56,80)半径为50规则下的圆心面积中的点
db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1})