Mongo索引

 一 索引简介

1.1 简介       

 mongo索引跟关系型数据的索引概念一样,相当于书的目录,能够快速定位数据。像关系型数据库一样我们可以通过explain看执行计划,如下图所示:


nscanned 扫描的文档数,millis 消耗的时间(毫秒)。可以发现这个是全表扫描,在username上面创建索引:

db.users.ensureIndex({"username":1})   //如果创建索引比较耗时,打开另外一个窗口查看进度 db.currentOp()

再次执行同样的查询,可以发现nscanned变成了1,millis也变成了个位数。


1.2 复合索引

在多个键上建立的索引叫做复合索引

1.2.1 键的方向

{"age":1,"username":-1} age 升序,username降序   跟另外一个索引是同一个含义{“age”:-1,"username":1}

1.2.2 覆盖索引

如果要查询的字段就在索引里面,就叫做覆盖索引扫描,这样避免了根据索引锁定位的地址再去找文档

1.2.3 隐 式索引

如果建立了索引{“a”:1,"b":1,"c":1,"d":1}, 相当于同时建立了{"a":1}, {"a":1,"b":1},{“a”:1,"b":1,"c":1}索引


1.3 索引使用

1.3.1 精确字段放前面,范围字段放后面

如果要进行查询{"age":47,"username":{"$gt":"user4","$lt":"user8"}},  那么建立索引age放前面,username放后面


1.4 索引对象和数组

1.4.1 嵌套文档索引

可以对嵌套字段建立索引,比如db.users.ensureIndex({"local.city":1})

1.4.2 数组索引

有一博客集合{"title":"I am a bird","content":"I think I am a bird,fly.....","comment":[{"date":"2017-08-01","content":"good"},{"date":"2017-08-02","content":"shit"}]};

comment评论是一个数组,可以再数组的元素 上建立索引 db.blogs.ensureIndex({"comment.date":1}), 这个时候,多少条评论,就有多少个索引条目,比单索引代价要高很多。


1.5 使用explain()和hint()

查看执行计划使用explain,


1. cursor: BtreeCursor age_l_username_l

BtreeCursor表示使用了索引,后面是具体索引名称

2.  isMultiKey: false

本次查询是否使用了多键索引

3. n: 8332

本次查询返回的文档数量

4. nscannedObjects: 8332

按照索引去磁盘查找实际文档次数,也就是索引的内容不足以返回给用户,还需要去查找具体内容

5. nscaned: 8332

查找过的索引条目数(索引扫描),检查过的文档数(全表扫描)

6. scanAndOrder: false

是否在内存中对结果进行排序

7. indexOnly: false

是否只使用索引就完成了本次查询

8. nYields: 0

为了让写入顺利进行,本次查询被暂停次数

9.  millis: 91

查询耗费的毫秒数

10. indexBounds:

索引的使用情况


1.6 查询优化器

mongodb的查询优化器与其他的数据有不同,如果一个查询是精确查询(要查询x,而x上刚好有索引),那么查询优化器就会使用索引。否则可能有好几个索引适合你的查询。mongbo不会去评估哪一个索引比较合适,而是所有的索引都生成一个执行计划,一起执行。最早返回100个结果的为胜利者。然后将最早的这个胜利者缓存起来,后续再执行的时候,就使用这个胜利者了。(如果数据发生大变动,胜利者可能也不是最优的了,建立索引,或者每执行1000次查询的时候,重新评估胜利者)


1.7 何时不应该使用索引

如果返回的数据量占比大于总数据量30%,不适合用索引。 如果发现使用了索引,可以强制全表扫描:

db.entries.find({"create_at":{"$lt":hourAgo}}).hint({"$natrual":1}); //natrual强制走全表扫描


1.8 索引类型

1.8.1 唯一索引

db.user.ensureIndex({"username":1},{"unique":true})

保证唯一性,但是索引是有大小的,字段不能大于1024字节,如果大于的话,这个文档不会被索引。

1.8.2 稀疏索引

如果有一个可能存在,也可能不存在的字段。当存在时候,必须唯一,就需要建立稀疏索引

db.user.ensureIndex({"email":1},{"unique":true, "sparse":true})

如果去掉unique,就是非唯一稀疏索引

注意使用索引的时候,如果字段为空,也会被存储在索引里面。查询的时候,可能会查询不到,需要注意。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章