MongoDB索引笔记

在 MongoDB 查询过程中,索引(Index) 起到非常重要的作用,如果没有索引,MongoDB将会执行全表扫描 。当然如果数据量比较少全表扫描的开销并不大,但如果集合文档数量到百万、千万甚至上亿的时候,一个查询耗费数十秒甚至几分钟都有可能,代价非常高昂。

MongoDB 使用 B-tree 作为索引底层的数据结构。
MongoDB 的索引是定义在 集合 (Collection) 级别的,支持对任何单个字段以及嵌套字段和数组建立索引。

MongoDB索引类型

默认的 _id index

MongoDB 在 集合(Collection)创建时会默认建立一个基于_id的唯一性索引作为 文档(Document) 的主键,这个索引无法被删除。

单字段索引 (Single Field Index)

单字段索引是最常见的索引形式,MongoDB默认创建的id索引也是这种类型,它是有顺序的。

以下操作在records集合的score字段上创建一个升序索引:

1
db.records.createIndex( { score: 1 } )

其中 1 代表升序索引,也可以通过**-1** 来指定降序索引,但是对于单字段索引来说,索引的顺序无关紧要,因为 MongoDB 支持任意顺序查找。

此外 MongoDB 还支持对嵌套字段(Embedded Field) 创建索引:

1
db.records.createIndex( { "location.state": 1 } )

复合索引 (Compound Index)

MongoDB支持对多个字段联合创建索引,称之为复合索引 (Compound Index)。复合索引中字段的顺序很重要,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,依次类推。

以下操作在item字段和stock字段上创建一个升序索引:

1
db.products.createIndex( { "item": 1, "stock": 1 } )

索引前缀(Prefixes)

prefix 是指索引字段的左前缀子集,如以下索引:

1
{ "item": 1, "location": 1, "stock": 1 }

这个索引包含以下索引前缀:

  • { item: 1 }
  • { item: 1, location: 1 }

所以只要语句满足索引前缀都是可以支持使用组合索引的:

  • the item field,
  • the item field and the location field,
  • the item field and the location field and the stock field.

相反如果不满足索引前缀则无法使用索引:

  • the location field
  • the stock field
  • the location and stock fields

如果您的集合同时具有复合索引和其前缀的索引(例如{ a: 1, b: 1 }{ a: 1 } ),如果两者都没有稀疏或唯一约束,则可以删除前缀上的索引(例如{ a: 1 } )。

索引的顺序(Sort Order)

对于单字段索引,排序的顺序无关紧要,复合索引则完全不一样,排序的顺序必须要和索引一致,逆序之后一致也可以

对于下面event集合,建立{ username: 1, date: -1 }复合索引:

1
db.events.createIndex( { "username": 1, "date": -1 } )

下面列出了上面复合索引支持的查询:

  • db.events.find().sort( { username: 1} )
  • db.events.find().sort( { username: -1} )
  • db.events.find().sort( { username: 1, date: -1 } )
  • db.events.find().sort( { username: -1, date: 1 } )

其他类型的索引

  • 多键索引 (Multikey Index
    当索引的字段为数组时,会自动为这个字段创建一个多键索引,能够加速对数组中元素的查找。

  • 哈希索引(Hashed Index
    是指按照某个字段的hash值来建立索引,目前主要用于MongoDB Sharded Cluster的Hash分片,hash索引只能满足字段完全匹配的查询,不能满足范围查询等。

  • 地理位置索引(Geospatial Index
    能很好的解决O2O的应用场景,比如『查找附近的美食』、『查找某个区域内的车站』等。

  • 文本索引(Text Index
    能解决快速文本查找的需求,比如有一个博客文章集合,需要根据博客的内容来快速查找,则可以针对博客内容建立文本索引。

索引属性(Index Properties)

MongoDB索引除了支持的众多索引类型外,还具有各种属性。

参考文档

MongoDB 索引