美文网首页
mongodb索引讲解与优化

mongodb索引讲解与优化

作者: 水车 | 来源:发表于2017-11-13 15:53 被阅读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。

    相关文章

      网友评论

          本文标题:mongodb索引讲解与优化

          本文链接:https://www.haomeiwen.com/subject/ltpzmxtx.html