MongoDB 基础(三)mongodb 中的索引使用

MongoDB中的索引和其他数据库索引类似,也是使用B-Tree结构。MongoDB的索引是在collection级别上的,并且支持在任何列或者集合内的文档的子列中创建索引。

 

下面是官方给出的一个使用索引查询和排序的一个结构图。

MongoDB 基础(三)mongodb 中的索引使用_第1张图片

所有的MongoDB集合默认都有一个唯一索引在字段“_id”上,如果应用程序没有为 “_id”列定义一个值,MongoDB将创建一个带有ObjectId值的列。(ObjectId是基于 时间、计算机ID、进程ID、本地进程计数器 生成的)


MongoDB 同样支持在一列或多列上创建升序或降序索引。

MongoDB还可以创建 多键索引、数组索引、空间索引、text索引、哈希索引,其属性可以是唯一性索引、稀疏性索引、TTL(time to live)索引。

 

索引的限制:

索引名称不能超过128个字符

每个集合不能超过64个索引

复合索引不能超过31列


MongoDB 索引语法

db.collection.createIndex({ <field>: < 1 or -1 > })

db.collection.ensureIndex({ <field>: < 1 or -1 > })

 

db.collection.createIndex( { "filed": sort } )

db.collection.createIndex( { "filed": sort , "filed2": sort } )

 

db.tab.ensureIndex({"id":1})

db.tab.ensureIndex({"id":1} ,{ name:"id_ind"})

db.tab.ensureIndex({"id":1,"name":1},{background:1,unique:1})

db.tab.ensureIndex( { "id" : "hashed" })

 

创建索引(两种方法)

 

 

filed :为键列

sort :为排序。1 为升序;-1为降序。

 

创建单列索引

创建索引并给定索引名称

后台创建唯一的复合索引

创建哈希索引

 (更多参数 看文章底部)

db.tab.indexStats( { index: "id_ind" } )

db.runCommand( { indexStats: "tab", index: "id_ind" } )

db.tab.getIndexes()

db.system.indexes.find()

(前2个似乎不能用,官方文档解释)

(not intended for production deployments)

查看索引

db.tab.totalIndexSize();

查看索引大小

db.tab.reIndex()

db.runCommand({reIndex:"tab"})

重建索引

db.tab.dropIndex(<indexname>)

db.tab.dropIndex("id_1")

db.tab.dropIndexes()

删除索引

<indexname>为getIndexes看到的索引名称

删除所有索引(注意!)

 

 



索引性能测试:

 

查看索引是否生效,分析查询性能有没有提高。先插入10万数据到集合tab

 

for(var i=0;1<=100000;i++){

var value=parseInt(i*Math.random());

db.tab.insert({"id":i,"name":"kk"+i,"value":value});

}

 

不知道是不是虚拟机的原因,插入了10分钟都未完成!~

自己又打开文件夹查看,一直进不去文件夹。结果客户端连接断开了!~查看服务竟然停了!

MongoDB 基础(三)mongodb 中的索引使用_第2张图片


重启服务,进去查看行数:96万!(过后再查看吧!就用这数据测试了!)

db.tab.find().count()


AnalyzeQuery Performance :http://docs.mongodb.org/manual/tutorial/analyze-query-plan/

分析函数

db.tab.find({"name":"kk50000"}).explain()

查询name=”kk50000”的执行分析

db.tab.find({"name":"kk50000"}).explain("queryPlanner")

db.tab.find({"name":"kk50000"}).explain("Verbosity")

db.tab.find({"name":"kk50000"}).explain("executionStats")

db.tab.find({"name":"kk50000"}).explain("allPlansExecution")

这3种方法执行结果完全包括上面这种的结果

db.tab.find({"name":"kk50000"}).explain()  结果做分析:

"cursor" : "BasicCursor",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 966423,

"nscanned" : 966423,

"nscannedObjectsAllPlans" : 966423,

"nscannedAllPlans" : 966423,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 7555,

"nChunkSkips" : 0,

"millis" : 4677,

"server" : "kk-ad:27017",

"filterSet" : false

游标类型。BasicCurso(扫描), BtreeCursor(索引)

是否多键(组合)索引

返回行数

扫描行数

扫描行数

所有计划扫描的次数

所有计划扫描的次数

是否在内存中排序

 

 

 

耗时(毫秒)

服务器

 



现在创建索引:

db.tab.createIndex({"name":1})

MongoDB 基础(三)mongodb 中的索引使用_第3张图片


db.tab.find({"name":"kk50000"}).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" : 1,

 "indexBounds" : {

         "name" : [

                 [

                         "kk50000",

                         "kk50000"

                 ]

         ]

 },

 "server" : "kk-ad:27017",

 "filterSet" : false

游标使用索引BtreeCursor = name_1

 

 

 

 

 

 

 

 

 

 

耗时:1毫秒

 

 

 

 

 

 

 

 

 

 


上面可以看到,没使用索引时,耗时4677毫秒,使用索引后,1毫秒!~并且不用全文档扫描。



索引提示(hint),当前collection创建的索引:

db.tab.ensureIndex({"id":1} ,{name:"id_ind"})

db.tab.ensureIndex({"id":1,"name":1},{background:1,unique:1})

db.tab.ensureIndex( { "name" :"hashed" })


现在查询 id=5000 的行(结果集为1行)

db.tab.find({"id": 5000}).explain()



查询使用的是id和name的复合索引。

"nscannedObjectsAllPlans" : 2,

 "nscannedAllPlans" : 2,

 

现在加上索引提示,强制使用索引:

db.tab.find({"id": 5000}).hint({"id":1}).explain()



这时使用的是单个键列为id的索引。

"nscannedObjectsAllPlans" : 1,

"nscannedAllPlans" : 1,

 

上面还可以看到,索引有个边界值“indexBounds”

MongoDB 基础(三)mongodb 中的索引使用_第4张图片


这个边界值在复合索引查询的时候,会导致扫描更多的数据。这是一个bug :wrong index ranges when using compound index on a list


当然我们也可以自己限制边界值。

db.tab.find().min({"id":5000}).max({ "id":5005})

MongoDB 基础(三)mongodb 中的索引使用_第5张图片


从上面看,实际只查询这个边界的内的数值。再查看执行计划:

db.tab.find().min({"id":5000}).max({ "id":5005}).explain()

MongoDB 基础(三)mongodb 中的索引使用_第6张图片


只是5行数据。如果查询id=5000的,但是索引边界又有问题,这时可以限制边界,如:

db.tab.find({"id": 5000 }).min({"id":5000}).max({ "id":5005})



在索引方法中,还有一个方法为cursor.snapshot(),它会确保查询不会多次返回相同的文档,即使是写操作在一个因为文档大小增长而移动的文档。但是,snapshot()不能保证插入或者删除的隔离性。snapshot()是使用在_id键列上的索引,因此snapshot()不能使用sort() 或 hint()。


分快照函数析snapshot()的查询结果:

db.tab.find({"id": 5000}).snapshot().explain()

MongoDB 基础(三)mongodb 中的索引使用_第7张图片

虽然使用了索引“_id”,但是把整个集合都搜索了!~

 

加索引提示看看,应该是报错的:

db.tab.find({"id": 5000}).snapshot().hint({"id":1})


果然是出错:snapshot 不能使用提示。



下面总结索引查询的一些方法:

Indexing Query Modifiers

db.tab.find({"id": 5000 }).hint({"id":1})

db.tab.find({"id": 5000 })._addSpecial("$hint",{"id":1})

db.tab.find({ $query: {"id": 5000 }, $hint: { "id":1 }})

使用键列id的索引查询id=5000的结果

db.tab.find({"id": 5000 }).snapshot()

db.tab.find({"id": 5000 })._addSpecial( "$snapshot", true )

db.tab.find({ $query: {"id": 5000 }, $snapshot: true })

使用快照的查询id=5000的结果

db.tab.find({"id": 5000 }).hint({"id":1}).explain()

db.tab.find({"id": 5000})._addSpecial("$explain",1)

db.tab.find({ $query: {"id": 5000 }, $hint: { "id":1 }, $explain: 1})

查看执行计划信息

索引边界设置

db.tab.find({"id": 5000 }).max({ "id":5005})

db.tab.find({ $query:{"id": 5000 },$max:{ "id": 5005}})

db.tab.find({"id": 5000 })._addSpecial("$max",{"id": 5005})

 

db.tab.find({"id": 5000 }).min({ "id":5000}).max({ "id":5005}).explain()

db.tab.find({ $query:{"id": 5000 },$max:{ "id": 5005},$min:{ "id": 5000}})

db.tab.find({"id": 5000 })._addSpecial("$min",{"id": 5000})._addSpecial("$max",{"id": 5005})



摘取了这了的一个总结:http://www.w3cschool.cc/mongodb/mongodb-indexing.html

Parameter

Type

Description

background

Boolean

建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false

unique

Boolean

建立的索引是否唯一。指定为true创建唯一索引。默认值为false.

name

string

索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。

dropDups

Boolean

在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.

sparse

Boolean

对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.

expireAfterSeconds

integer

指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。

v

index version

索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。

weights

document

索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。

default_language

string

对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语

language_override

string

对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.



更多参考官方文档:Indexes


你可能感兴趣的:(MongoDB 基础(三)mongodb 中的索引使用)