MongoDB(7)索引管理

本文介绍了MongoDB中索引的基本概念、创建方法及其对查询性能的影响。包括索引的优势与代价、索引覆盖查询的概念、如何创建不同类型的索引及其实例演示。

MongoDB 入门专栏

http://blog.youkuaiyun.com/column/details/19681.html


MongoDB 索引

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构;

使用索引的优点:
  • 索引通常能够极大的提高查询的效率,这是由于索引储存在内存中,同时索引本身的遍历效率必普通集合更高;

使用索引带来的代价:
  • 额外的操作开销,在进行插入、更新、删除操作时,也需要对索引进行操作,如果是查询少、更改多的集合,使用索引是很不划算的;
  • 额外的内存开销,由于索引是储存在内存中的,应该确保索引大小不超过内存限制(如果索引大小操作内存限制,mongodb 会删除一些索引,导致性能下降);

mongdb 的索引存在以下限制:
  • 一个集合的索引不能超过 64 个;
  • 索引名长度不能超过 128 个字符;
  • 一个复合索引最多只能由 31 个;

索引不能用以下查询:
  • 正则表达式查询,$regex;
  • 非操作符查询,如 $nin,$not 等;
  • 算术运算符,如 $mod 等;
  • $where 操作符子句;


创建索引

为集合创建索引使用可以 ensureIndex( {<key>:<1|-1>}, {<option>} )
  • key:索引使用的键,1 表示正序,-1 表示倒序;
  • option:可接受参数,参数列表如下:
    • background:<boolean> - 创建索引是否会阻塞其他数据库操作,默认值 false;
    • name:<string> -  索引的名称,如果未指定,mongodb会通过索引的字段名和排序顺序生成一个索引名称;
    • unique:<boolean> - 建立索引是否唯一,默认为 false;
    • dropDups:<boolean> - 在建立唯一索引时,是否会删除重复记录,默认为 false;
    • sparse:<boolean> - 对文档中不存在的字段是否不启用索引,如果设置为 true,在索引字段中不会出现查询不包含对应字段的索引,默认为 false;
    • expireAfterSeconds:<integer> - 设定查询集合在内存中的生存时间(TTL设定);
    • v:<index version> - 索引的版本号,默认为 mongo 创建索引时运行的版本;
    • weights:<document> - 索引的权重值,表示该索引对于其他索引字段的得分权重,范围在 [1,99999];
    • default_language:<string> - 指定文本索引停用词、词干、词器的规则的咧白哦,默认为 en 英语;
    • language_override:<string> - 指定文本索引包含在文档中的字段名、语言覆盖默认的 language,默认为 language;
 
# 为 col 集合创建索引,索引字段为 title,正序
db.col.ensureIndex( {title:1} )
# 为 col 集合创建复合索引,索引字段为 title,score,正序,正序
db.col.ensureIndex( {title:1, score:1} )
# 创建索后台进行
db.col.ensureIndex( {title:1}, {backgroud:true} )

索引覆盖查询

在创建了索引之后,mongodb 在进行索引时,如果查询的字段已经被建立了索引,那么 mongodb 并不会真正去数据库中查询这些字段,而是直接在已经建立的索引中提取数据(这个速度远远高于直接在数据库中查询),即此时 mongodb 会使用索引覆盖查询;
需要注意的是,mongodb 默认的查询会返回 _id 字段,如果没有对 _id 字段进行索引,是不会使用索引覆盖查询的;
 
db.col.ensureIndex( {title:1, score:1} )  # 为 col 集合中的 title、score 字段建立索引;
db.col.find( {title:"hello world"}, {score:1, _id:0} ) # 该查询会被以上索引覆盖,mongodb 直接在索引中查询;
db.col.find( {title:"hello world"}, {score:1} )        # 该索引没有被以上索引覆盖,mongodb 在数据库中查询,原因是含有没有被索引覆盖的 _id 字段;
db.col.find( {title:"hello world"} )                   # 该索引没有被以上索引覆盖,原因是含有没有被索引覆盖的 _id 字段;
※ 如果是以下类型查询,无法使用索引覆盖查询:
  • 索引字段是一个数组;
  • 索引字段是一个子文档;

索引数组字段 

假设要检索下列 user 文档的 tages 数组:
 
{  
   "name":"assad",
   "tags": [
      "coder",
      "fat nerd",
      "philosophy♂"
   ]
 }
可以使用以下命名来创建数组索引,当为整个数组创建索引之后,会为数组里的所有值单独创建索引:
 
> db.users.ensureIndex( {tages:1} )
验证检索结果:
 
> db.users.find( {tages:"coder"} ).explain()

索引子文档字段

假设要检索下列 user 文档的 address 子文档,通过 city、state、pincode 字段来创建 user 的检索,由于这些字段为 user 的 子文档 address 的字段,需要对 address 文档创建检索:
 
{  
   "name":"assad",
   "address": {
      "city": "Guanzhou",
      "state": "Guangdong",
      "pincode": "510000"
   }
 }
可以使用以下创建 address 子文档全部字段的索引:
 
> db.users.find( {address.city:1, address.state:1, address.pincode:1} )
验证检索结果:
 
> db.users.find( {address.city:"Guangdong", address.state:"Gunagzhou" } ).explain()

查看索引 & 删除索引

 
# 查看数据库中所有的索引
> db.system.indexs.find()
.....
# 查看集合中的索引
> db.col.getIndexes()
[
   {
       "v" : 2,
       "key" : {
           "_id" : 1
       },
       "name" : "_id_",
       "ns" : "testdb.articles"
   },
   {
       "v" : 2,
       "key" : {
           "title" : 1
       },
       "name" : "title_1",
       "ns" : "testdb.articles"
   }
]
# 查看索引大小,单位 bytes
> db.articles.totalIndexSize()
53248
# 删除所有索引
> db.articles.dropIndexes()
# 删除指定 name 的索引
> db.srticles.dropIndex("title_1")

索引查询分析

explain() 方法
 可以使用 explain() 方法用于获取查询的信息、索引使用情况、查询统计等信息,方便对索引进行优化;
 
> db.articles.ensureIndex({author:1,title:1})     # 创建索引
> db.articles.find({author:"assad"},{title:1,_id:0}).explain()    # 使用 explain 函数进行查询分析
返回信息中于索引相关的信息:
 
  "inputStage" : {
      "stage" : "IXSCAN",
      "keyPattern" : {
              "author" : 1,
              "title" : 1
      },
      "indexName" : "author_1_title_1",
      "isMultiKey" : false,
      "multiKeyPaths" : {
              "author" : [ ],
              "title" : [ ]
      },
      "isUnique" : false,
      "isSparse" : false,
      "isPartial" : false,
      "indexVersion" : 2,
      "direction" : "forward",
      "indexBounds" : {
              "author" : [
                      "[\"assad\", \"assad\"]"
              ],
              "title" : [
                      "[MinKey, MaxKey]"
              ]
      }
  }
hint() 方法
hint() 方法用于强制 mongodb 使用一个指定的索引,如下,同样也可以使用 explain() 方法来分析以下索引;
 
>db.users.find({author:'assad'},{title:1,_id:0}).hint({author:1,title:1})



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值