索引
1.创建简单索引
准备数据
向books集合中插入20w条数据:
> 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:65535})
var end = new Date();
end-start
结果:328ms 与机器性能相关
1.2 为number键创建索引
//为number键创建正序索引
db.books.ensureIndex({number:1})
1.3 再次测试查询效率
var start = new Date();
db.books.find({number:65535})
var end = new Date();
end-start
结果:47ms !! 这是一个数量级的提升
2.索引使用需要注意的地方
2.1创建索引的时候注意
1:创建正序索引 -1:创建倒序索引
2.2 索引的创建在提高查询性能的同时,会影响插入的性能
对于经常查询少查询的文档可以考虑使用索引
2.3 符合索引要注意索引的先后顺序
问:为每个键创建索引是不是性能就会提高?
索引不是万能的(要合理创建索引)
在做排序工作的时候如果是超大数据量也可以考虑加上索引
用来提高排序的性能
3.索引的名称
3.1 使用VUE来查看索引的名称
3.2 创建索引的用时指定索引的名字
db.books.ensureIndex({name:-1},{name:”bookname”})
4.唯一索引
4.1如何避免文档books插入重复数值?
建立唯一索引
db.books.ensureIndex({name:-1},{unique: "bookname"})
测试:
尝试再次插入重复数值
db.books.insert({name:”1book”})
出现错误:
4.2建立唯一索引之前已经有了重复的数值,该如何处理?
在建立索引的时候有一个可选项:建立索引同时剔除重复值
操作:
db.books.ensureIndex({name:-1},{unique:ture,dropDups:true})
5.Hint 使用指定的索引进行查询
如何强制使用指定的索引进行查询呢?
db.books.find ({name:“1book”,number:1}).hint({name:-1})
指定索引必须是已经创建了的索引
否则出现如下错误:
6.Explain 使用
如何详细查看本次查询使用哪个索引和查询数据的状态信息?
调用explain()方法
> db.books.find({number:65535}).explain()
{
"cursor" : "BtreeCursor number_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"number" : [
[
65535,
65535
]
]
},
"server" : "itcast01:27017",
"filterSet" : false
}
“cursor”:”BtreeCursor number_1” 使用的索引
“nscanned”:1 查到几个文档
“millis”:0 查询耗时
2.索引的管理
1. 使用shell查看数据库已经建立的索引system.indexes
> db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "admin.admin" }
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "admin.text" }
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "admin.user" }
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "admin.persons" }
{ "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "admin.books" }
{ "v" : 1, "key" : { "number" : 1 }, "name" : "number_1", "ns" : "admin.books" }
2.后台执行
执行创建索引的过程会暂时锁表的问题如何解决?
为了不影响查询,我们可以让索引的创建过程在后台完成
db.books.ensureIndex({name:-1},{background:true})
3.删除索引
精确删除索引
db.runCommand({dropIndexes : "books" , index:”name_-1”})
或者:
db.COLLECTION.dropIndex("IndexName")
批量删除索引
db.runCommand({dropIndexes: "集合名称",index: "*"})
3.空间索引
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
db.map.insert(map[i])
}
添加2D索引
db.map.ensureIndex({"gis":"2d"},{min:-1,max:201})
1.查询出距离点(70,180)最近的3个点
默认会建立一个[-180,180]之间的2D索引 查询点(70,180)最近的3个点
db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3)
{ "gis" : { "x" : 70, "y" : 180 } }
{ "gis" : { "x" : 75, "y" : 180 } }
{ "gis" : { "x" : 65, "y" : 185 } }
2.查询以点(50,50)和点(190,190)为对角线的正方形中的所有的点
db.map.find({gis:{"$within":{$box:[[50,50],[190,190]]}}},{_id:0,gis:1})
{ "gis" : { "x" : 185, "y" : 150 } }
{ "gis" : { "x" : 75, "y" : 180 } }
{ "gis" : { "x" : 70, "y" : 180 } }
{ "gis" : { "x" : 65, "y" : 185 } }
{ "gis" : { "x" : 65, "y" : 80 } }
{ "gis" : { "x" : 55, "y" : 80 } }
{ "gis" : { "x" : 60, "y" : 55 } }
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 185, "y" : 185 } }
3.查询出以圆心为(56,80)半径为50规则下的圆心面积中的点
db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1})
{ "gis" : { "x" : 55, "y" : 80 } }
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 60, "y" : 55 } }
{ "gis" : { "x" : 65, "y" : 80 } }