zoukankan      html  css  js  c++  java
  • MongoDB基础教程系列--第六篇 MongoDB 索引

     返回目录

    使用索引可以大大提高文档的查询效率。如果没有索引,会遍历集合中所有文档,才能找到匹配查询语句的文档。这样遍历集合中整个文档的方式是非常耗时的,特别是处理大数据时,耗时几十秒甚至几分钟都是有可能的。

    创建索引

    MongoDB 中,使用 ensureIndex() 方法创建索引。

    格式

    db.COLLECTION_NAME.ensureIndex({KEY:1})

    其中,KEY表示要创建索引的字段名称,1 表示按升序排列字段值。-1 表示按降序排列。

    范例

    1、给 user 集合中 name 字段添加索引

    >db.user.ensureIndex({"name":1})
    >
    

    MongoDB 中用 db.collection.getIndexes() 方法查询集合中所有的索引,我们查询一下 user 中所有的索引。

    >db.user.getIndexes()
    [
          {
                 "v" : 2,
                 "key" : {
                             "_id" : 1
                 },
                 "name" : "_id_",
                 "ns" : "liruihuan.user"
          },
          {
                 "v" : 2,
                 "key" : {
                             "age" : 1
                 },
                 "name" : "name_1",
                 "ns" : "liruihuan.user"
          }
    ]

    我们发现 user 中有两个索引,其中索引 "_id_" 是我们创建 user 集合时,MongoDB 自动生成的索引。第二个索引就是我们刚才创建的索引,其中,name 值"name_1"表示索引名称,MongoDB 会自动生成的索引名称。当然,我们也可以自己指定索引的名称。

    2、给 user 集合中 age 字段添加索引,并指定索引名称为 "index_age_esc"。

    >db.user.ensureIndex({"age":1},{name:"index_age_esc"})
    >db.user.getIndexes()
    [
          {
                 "v" : 2,
                 "key" : {
                             "_id" : 1
                 },
                 "name" : "_id_",
                 "ns" : "liruihuan.user"
          },
          {
                 "v" : 2,
                 "key" : {
                             "age" : 1
                 },
                 "name" : "index_age_esc",
                 "ns" : "liruihuan.user"
          }
    ]

    指定索引名称用到的 name 参数,只是 ensureIndex() 方法可接收可选参数的其中一个,下表列出了 ensureIndex() 方法可接收的参数

    ParameterTypeDescription
    background 布尔值 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false
    unique 布尔值 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
    name 字符串 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
    dropDups 布尔值 在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
    sparse 布尔值 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
    expireAfterSeconds 整型 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
    v 索引版本 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
    weights 文档(document) 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
    default_language 字符串 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
    language_override 字符串 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

    唯一索引

    MongoDB和关系型数据库一样都可以建立唯一索引,重复的键值就不能重新插入了,MongoDB 用 unigue 来确定建立的索引是否为唯一索引,true 表示为唯一索引,下面给 user 集合的 name 字段指定唯一索引

    >db.user.ensureIndex({"name":1},{unique:true})
    
    > db.user.find()
    { "_id" : ObjectId("58e1d2f0bb1bbc3245fa754b"), "name" : "liruihuan", "age" : 18,"sex":"man" }
    
    >db.user.insert({"name":"liruihuan","age":18})
    E11000 duplicate key error collection: liruihuan.user index: name_1 dup key: { : "liruihuan"
    

    可以看出,创建了唯一索引的字段,是不能再插入 "liruihuan" 的 name 值的。

    复合索引

    ensureIndex() 方法中你也可以设置使用多个字段创建索引

    范例

    >db.user.ensureIndex({"name":1,"age":1})
    >db.user.getIndexes()
    [
          {
                 "v" : 2,
                 "key" : {
                             "_id" : 1
                 },
                 "name" : "_id_",
                 "ns" : "liruihuan.user"
          },
          {
                 "v" : 2,
                 "key" : {
                             "name" : 1,
                             "age" : 1
                 },
                 "name" : "name_1_age_1",
                 "ns" : "liruihuan.user"
          }
    ]

    删除索引

    MongoDB 用dropIndex() 方法删除索引

    格式

    db.COLLECTION_NAME.dropIndex()
    

    注:dropIndex() 方法可根据指定的索引名称或索引文档删除索引(_id上的默认索引除外)

    范例

    我们用两种方式删除掉 user 中 name 字段上的索引

    >db.user.dropIndex("name_1")     #根据索引名称删除索引
    >db.user.dropIndex({"name":1})   #根据索引文档删除索引
    

    还可以用 dropIndexes() 删除集合中所有索引(_id上的默认索引除外)

    >db.user.dropIndexes()

    查询分析

    查询分析是查询语句性能分析的重要工具。

    MongoDB 中查询分析用 explain() 和 hint() 方法

    范例

    我们向集合 user 中插入20万条数据,利用 explain() 查询建立索引前后,执行时间的比较,来看看建立索引对查询效率的提高程度。

    第一步,向 user 中插入20万条数据

    >db.user.remove({})
    >for(var i = 0; i <200000; i++){db.user.insert({"name":"lrh"+i,"age":18})}
    

    第二步,删除 user 集合中字段 name 上的索引,然后查询 name = "lrh100000",利用explain("executionStats")查询此时执行的时间。说明:MongoDB explain() 方法在3.0以后版本中发生了很大改变,3.0之前版本直接用explain()就可以,不用传参数,如果想详细了解,请访问官网

    >db.user.dropIndexes()      #删除所有索引
    db.user.find({"name":"lrh100000"}).explain("executionStats")
    {
           "queryplanner" : {
                     ......
           },
           "executionStats" : {
                     "executionTimeMillis" : 109
                     ...... 
           }
    }

    explain.executionStats.executionTimeMillis:表示查询所用的时间,单位是毫秒。

    我们可以清楚的看出,没用索引查询用到的时间是 109 毫秒。

    第三步,给 user 集合中 name 字段添加索引,然后再查询同一个条件,看执行查询所用了多久时间。

    >db.user.ensureIndex({"name":1})     
    >db.user.find({"name":"lrh100000"}).explain("executionStats")
    {
           "queryplanner" : {
                     "winningPlan" : {
                            "inputStage" : {
                                     "indexName" : "name_1"
                                     ......
                            }
                            .......
                     }
                    .......
           },
           "executionStats" : {
                     "executionTimeMillis" : 1
                     ...... 
           }
    }
    

    如果用到了索引,explain() 方法会返回 winningPlan,标识用到的索引名称 indexName

    我们可以清楚到处,用了索引,执行时间只有 1 毫秒,可以看出,查询效率的提高可不是一星半点。

    注:如果想更详细的了解 explain() 返回的参数,可以去官网看一下

    第四步,这一步我们重点看看 hint() 方法的用法。hint() 方法用来强制 MongoDB 使用一个指定的索引。

    我们给 user 再添加一个 {"name":1, "age":1},利用 explain() 方法,看一下用到了哪个索引。

    >db.user.ensureIndex({"name":1, "age":1})     
    >db.user.find({"name":"lrh100000"}).explain("executionStats")
    {
           "queryplanner" : {
                     "winningPlan" : {
                            "inputStage" : {
                                     "indexName" : "name_1_age_1"
                                     ......
                            }
                            .......
                     }
                    .......
           }
           ......
    }
    

    可以看出,此时用到的索引是 "name_1_age_1",如果我们想用索引 "name_1",就可以用 hint() 方法指定。

    >db.user.find({"name":"lrh100000"}).hint({"name":1}).explain("executionStats")
    {
           "queryplanner" : {
                     "winningPlan" : {
                            "inputStage" : {
                                     "indexName" : "name_1"
                                     ......
                            }
                            .......
                     }
                    .......
           }
           ......
    }

    业精于勤,荒于嬉;行成于思,毁于随。

    如果你觉得这篇文章不错或者对你有所帮助,可以通过右侧【打赏】功能,给予博主一点点鼓励和支持

  • 相关阅读:
    oracle 11g 更改字符集,9i导入11g 出现 ORACLE 错误 12899 处理
    使用XUACompatible来设置IE浏览器兼容模式
    server2008中如何关闭internet explorer增强的安全配置
    oracle修改密码
    ORA28000: the account is locked的解决办法
    C#与word
    Javascript 使用大全
    双机热备、集群及高可用性入门(转载 rdxx.com)
    table画细线
    CSS总结
  • 原文地址:https://www.cnblogs.com/liruihuan/p/6682575.html
Copyright © 2011-2022 走看看