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

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

 

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

 

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

 

MongoDB 一样支持在一列或多列上建立升序或降序索引。数组

MongoDB还能够建立 多键索引、数组索引、空间索引、text索引、哈希索引,其属性能够是惟一性索引、稀疏性索引、TTL(time to live)索引。服务器

 

索引的限制:dom

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

每一个集合不能超过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分钟都未完成!~

本身又打开文件夹查看,一直进不去文件夹。结果客户端链接断开了!~查看服务居然停了!

 

 

重启服务,进去查看行数: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})

 

 

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”

 

 

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

 

 

固然咱们也能够本身限制边界值。

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

 

 

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

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

 

 

只是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()

 

虽然使用了索引“_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

相关文章
相关标签/搜索