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 thelocation
field, - the
item
field and thelocation
field and thestock
field.
相反如果不满足索引前缀则无法使用索引:
- the
location
field - the
stock
field - the
location
andstock
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索引除了支持的众多索引类型外,还具有各种属性。
-
可以对某个时间字段,指定文档的过期时间。
-
索引字段不出现重复值(如:_id)。
-
只针对符合某个特定条件的文档建立索引。
-
忽略索引键值的大小写.
-
只针对存在索引字段的文档建立索引。