MongoDB 索引

简介

索引的作用是为了提升查询效率,在查询操作中,如果没有索引,MongoDB 会扫描集合中的每个文档,以选择与查询语句匹配的文档。如果查询条件带有索引,MongoDB 将扫描索引, 通过索引确定要查询的部分文档,而非直接对全部文档进行扫描。

索引可以提升文档的查询速度,但建立索引的过程需要使用计算与存储资源,在已经建立索引的前提下,插入新的文档会引起索引顺序的重排。

MongoDB 的索引是基于 B-tree 数据结构及对应算法形成的。树索引存储特定字段或字段集的值,按字段值排序。索引条目的排序支持有效的等式匹配和基于范围的查询操作。

B-tree

TODO

索引类型及创建

MongoDB 中的索引类型有:
普通索引,复合索引,多键值索引,地理索引,全文索引,散列索引等。

普通索引

db.collection.createIndex({"field": 1})   // 1 升序  -1 降序

复合索引

复合索引包括多个字段,支持在多个字段上进行匹配查询。

db.collection.createIndex({<key1>:<type>, <key2>:<type2>, ...})

tips: 复合索引一定要注意顺序问题。

多键值索引

多键值索引指的是为包含数组的字段建立索引,MongoDB 会为数组中的每个元素都创建索引。

db.collection.createIndex({<key>: <1 or -1>})

地理索引

地理索引包含两种地理类型,如果需要计算的地理数据表示为类似于地球的球形表面上的坐标,则可以使用 2dsphere 索引。

通常可以按照坐标轴、经度、纬度的方式把位置数据存储为 GeoJSON 对象。GeoJSON 的坐标参考系使用的是 wgs84 数据。如果需要计算距离(在一个欧几里得平面上),通常可以按照正常坐标对的形式存储位置数据,可使用 2d 索引。

db.colleciton.createIndex({<localtion field>: "2d"})

全文索引

MongoDB 的全文检索提供三个版本,用户在使用时可以指定相应的版本,如果不指定则默认选择当前版本对应的全文索引。

MongoDB 提供的文本索引支持对字符串内容的文本搜索查询,但是这种索引因为需要检索的文件比较多,因此在使用的时候检索时间较长。

db.collection.createIndex ({ key: "text" })

散列索引

散列(Hashed)索引是指按照某个字段的散列值来建立索引,目前主要用于 MongoDB Sharded Cluster 的散列分片,散列索引只能用于字段完全匹配的查询,不能用于范围查询等。

db.collection.createIndex({_id: "hashed"})

MongoDB 支持散列任何单个字段的索引,但是不支持多键(即数组)索引。

索引参数

上面列出的都是索引的类别,在每个索引的类别上还可以加上一些参数,使索引更加具有针对性,常见的参数包括稀疏索引、唯一索引、过期索引等。

稀疏索引

只检索包含具有索引字段的文档,即使索引字段包含空值,检索时也会跳过所有缺少索引字段的文档。因为索引不包含集合的所有文档,所以说索引是稀疏的。相反,非稀疏索引包含集合中的所有文档,存储不包含索引字段的文档的空值。

db.collection.createlndex ({ "key" : 1 }, { sparse : true })

如果设置了唯一索引,新插入文档时,要求 key 的值是唯一的,不能有重复的出现:

db.collection.createlndex ({ "key" : 1 }, { unique: true })

过期索引

一种特殊的单字段索引,MongoDB 可以用来在一定时间或特定时间后从集合中自动删除文档。

过期索引对于处理某些类型的信息非常有用,例如,机器生成的事务数据、日志和会话信息,这些信息只需要在数据库中存在有限的时间,不需要长期保存。

db.collection.createlndex( {"key" : 1 }, { expireAfterSeconds: 3600 })

需要注意的是,MongoDB 是每 60s 执行一次删除操作,因此短时间内执行会出现延迟现象。

查看索引

db.collection.getIndexes()

删除索引

MongoDB 提供的两种从集合中删除索引的方法如下:

db.collection.dropIndex()

db.collection.dropIndexes()

若要删除特定索引,则可使用该 db.collection.droplndex() 方法。

例如,以下操作将删除集合中 score 字段的升序索引:

db.records.dropIndex ({ "score" : 1 })  //升序降序不能错,如果为-1,则提示无索引

还可以使用 db.collection.droplndexes() 删除除 _id 索引之外的所有索引。

例如,以下命令将从 records 集合中删除所有索引:

db.records.dropIndexes()

修改索引

若要修改现有索引,则需要删除现有索引并重新创建索引。