mongodb索引讲解与优化

2017-11-13  本文已影响166人  水车

语句集合

语句 功能 备注
db.name. getIndexes() 查询索引
db.name.totalIndexSize() 查询索引大小
db.name.dropIndex("indexName") 删除索引
db.name.dropIndex(‘*’) 删除name集合中的所有索引 _id索引不会删除
没有修改索引的方法 如果想想修改索引 先删除旧索引,再重新创建索引
db.name.ensureIndex() 创建索引

索引种类

种类 解释 备注
默认索引 Mongodb每个collection都会有一个默认主键_id,这个不能删除、也不会更名。当collection创建后,系统会自动创建一个”id”的索引,这个也是无法删除与更名的
单列索引 在单个栏位上创建的索引 eg:需要对Mail的read创建升序索引:db.Mail.ensureIndex({‘read’:1})
组合索引 对多个键创建的索引 eg:需要对Mail的user与folderId创建降序索引:db.Mail.ensureIndex({‘user’:-1,’folderId’:-1})
子文档索引 可以为内嵌文档的键创建索引,这种与普通索引没有什么区别 eg:需要对Mail中的attachments下的filename创建索引: db.Mail.ensureIndex({‘attachments.filename’:1})
注意:attachments.filename必须位于’’之中,否则会报错
唯一索引 唯 一索引可能确保collection的每一个document指定的键的唯一性。当文档不存在指定键时,会被认为键值是“null”,所以“null”也 会被认为是重复的,所以一般被作为唯一索引的键,最好都要有键值对 要保证Mail中每个用户的mailfilename的唯一性:db.Mail.ensureIndex({‘user’:1,‘filename’:1},{name:’index1’,‘unique’:true})

当为已有的collection增加唯一索引时,可能会有数据已经重复了。有时候可能希望将所有包含重复的文档都删除,可能在创建唯一索引时,使用dropDups选项:
db.Mail.ensureIndex({‘user’:1,‘filename’:1},{‘unique’:true,’dropDups’:true})
这个会将重复的数据只保留一份,不过有点鲁莽,如果数据很重要的话,建议不好这样做。

注意了:
Insert并不检查文档是否插入过,所以确保数据的唯一性,可能要用安全模式插入才行。这样,在插入时,如果有重复就会有错误提醒
Sparse索引 Sparse index解决索引文件过大的问题,有时候我们要索引的某个属性并非是所有记录都有,普通的索引是将所有的记录都包含进来,而sparse索引则仅包含含 有这个属性的记录,它不会对该项值为空的行作索引。这样就大大减小了某些列的索引大小。目前的限制是,sparse index只能包含一个属性。 eg:在Mail中有个标签属性labels,这个属性是唯一的,且有值的情况也不多,这种情况就最适合用sparse索引 了,创建索引的命令为:
db.Mail.ensureIndex({labels:1},{sparse:true})
Covered 索引 如果你查找的值正好是在索引中,则可以直接返回索引中存的值,而不用到数据文件中查找。(这个在传统关系型数据库中也有实现),不过,必须满足以下条件:
1:必须提供准备的返回字段,以便可以直接从索引库中查询
2:必须明确地排除使用_id字段{_id:0}当用explain时,当indexOnly=true,表示有用到covered index
// do a login with a covered index, returning the users roles/groups
> db.users.ensureIndex( { username : 1, password : 1, roles : 1} );
> db.users.save({username: "joe", password: "pass", roles: 2})
> db.users.save({username: "liz", password: "pass2", roles: 4})
> db.users.find({username: "joe"}, {_id: 0, roles: 1})
{ "roles" : 2 }
> db.users.find({username: "joe"}, {_id: 0, roles: 1}).explain()
{
"cursor" : "BtreeCursor username_1_password_1_roles_1",
...
"indexOnly" : true,
...
}

索引触发条件

索引命中:

假设索引为:

{a:1,b:1,c:1,d:1}:

实际上是有了下列索引

{a:1},{a:1,b:1},{a:1,b:1,c:1},{a:1,b:1,c:1,d:1}

但是使用{b:1}、{a:1,c:1}等索引的查询是会被优化的,只有使用索引前部的查询才能使用该索引。

Mongodb的查询优化器会重排查询项的顺序,以便命中索引,比如:查询{x:’a’,y:’b’}的时候,如果已有了{y:1,x:1}的索引,mongodb也会自己找到并命中的。

创建索引的缺点是每次插入、更新与删除时都会产生额外的开销,这是因为数据库不但需要执行这些操作,还是处理索引,因些,要尽量可能少创建索引。每个集合默认的最大索引个数为64个。

查询时,不要使用$ne or $nin,这样不能命中索引

使用explain查看

新版explain使用说明

db.collection.find(query).explain();

返回的信息如下

{“cursor” : “BasicCursor”,

“indexBounds” : [ ],

“nscanned” : 57594,

“nscannedObjects” : 57594,

“nYields” : 2 ,

“n” : 3 ,

“millis” : 108,

“indexOnly” : false}

现实结果可以得知cursor的类型,DB扫描的数据数,返回的数据数,还有执行的毫秒数。

“cursor” : “BasicCursor”:

命中的索引,当为BasicCursor时表示没有命中任何索引

indexBounds: 所使用的索引,被设置为表示为索引扫描的关键边界。

nscanned – 扫描的数据条数。

nscannedObjects – 扫描对象的数。

nYields – 查询所产生的锁的个数。

isMultiKey- MongoDB中提供了可以自动索引数组对象的值

If true, a multikey index was used.

n- 返回文档的数量

millis- 数据库中执行查询的时间

indexOnly – 是否使用了covered index。

上一篇下一篇

猜你喜欢

热点阅读