MongoDB Indexing
- 索引的概述
- 单键索引 (Single key index)
- 复合键索引
- 稀疏索引 (Sparse index)
- 多键索引
- 哈希索引 (Hashed index)
- Geospacial index
- 索引管理
- References
索引的概述
索引可以显著的减少访问文件所需的时间。
如果没有索引,必须访问集合中的所有文档。
单键索引最适合{“key”:“value”}查询条件。
对于多个键的查询条件,例如{$and:[{“key1”:“value1”},{“key2”:“value2”}]}复合索引是最好的选择。
如果我们在(key1, key2)上有一个复合索引,那么key1上的第二个索引实际上是不需要的,但是它仍然可以使访问速度加快一点。
如果我们在(key1, key2)上有一个复合索引,那么key2上的第二个索引会大大加快访问速度。因此复合索引中的键顺序非常重要!
单键索引 (Single key index)
_id上的索引是一个自动创建的单键索引。
因此搜索“_id”的值是可能的快速搜索。
下面的命令上在code上创建了一个单键unique索引。
db.department.createIndex( {"code": 1}, {"unique":true} )
索引是唯一(unique)的,因为它强制与键代码相关联的值的唯一性,例如,集合中的每个文档都有与键代码相关联的不同值。
如果试图插入两个具有相同键代码值的文档,则无法强制执行键约束。
在插入任何数据之前,应该创建唯一索引。
不能在存在重复键的集合上创建唯一索引。
在budget上创建非唯一索引。
db.department.createIndex( {"budget": 1}, {"unique": false} )
复合键索引
复合索引是每个条目(entry)由多个键组成的单个索引。
下面的命令是在键budget和total_staff_number上创建一个复合键非惟一索引:
db.department.createIndex( {"budget":1, "total_staff_number":1}, {"unique":false} )
使用以下查询时就可以用到这个符合键索引:
db.department.find({"budget":2000, :"total_staff_number":5})
稀疏索引 (Sparse index)
MongoDB的索引默认是密集的。
在每个文档的密集索引中,有一个索引键,即使文档缺少一个键。
在一个索引中存在一个空条目,并且可以对类似的查询使用一个索引:
b.department.find({"budget":null})
密集索引在以下情况下不方便使用:
- unique index on a ?eld that doesn’t appear in every document in a collection is needed.
- 集合中的大量文档没有索引键。
在稀疏索引中,只有具有索引键值的文档才被索引:
db.department.createIndex( {"total_staff_number":1}, {"unique":false, "sparse":true} )
多键索引
在多键索引中,索引中的多个条目引用同一个文档。
多键索引在索引值为数组的领域非常有效。
db.department.createIndex( {"course.code":1} )
courses.code 数组的每一个值都将出现在索引中。
对任何数组值的查询都可以使用索引来定位文档。
哈希索引 (Hashed index)
哈希索引中,键成为哈希索引的参数,哈希索引的结果确定文档在哈希桶中的位置。
哈希值将决定文档的顺序:
db.department.createIndex( {"name":"hashed"} )
哈希索引的限制:
- 可以使用索引处理相等查询。
- 范围查询不能使用哈希索引。
- 不允许使用多键哈希索引。
- 浮点值在哈希之前被转换为整数;1.4和1.5在散列索引中具有相同的值。
Geospacial index
Geospacial index允许基于每个文档中存储的纬度和经度值查找靠近给定位置的文档。
Geospacial index可用于有效的计算地理距离,包括地球的曲率。
MongoDB支持不同种类的索引,然而,只有下面列出的前两种索引可以组合为复合索引。
- 1: 升序二叉树索引
- -1: 降序二叉树索引
- “哈希”:哈希表索引;用精确值查找非常快,特别是在非常大的集合中。但不适用于不精确查询(“$ gt”、“$regex”或类似查询)
- “文本”:为用自然语言搜索字符串中的单词而设计的文本索引
- “2d”:平面上的地理空间索引
- “2dsphere”:球体上的地理空间索引
索引管理
查看索引清单:
db.department.getIndexes()
输出如下:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.department"
}
]
创建一个索引:
db.department.createIndex( {"name":"hashed"} )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
再次查看索引清单:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.department"
}
{
"v" : 2,
"key" : {
"name" : "hashed"
},
"name" : "name_hashed",
"ns" : "test.department"
}
]
查看到了新创建的索引。
删除 name_hashed索引
db.department.dropIndex("name_hashed")
db.department.getIndexes()
在这里插入代码片
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.department"
}
]
在加载数据之前创建索引允许在插入数据时增量地构建索引。
在已经加载的集合上创建索引可能需要很长时间。
以在后台创建索引,而不需要关闭数据库系统。
db.department.createIndex( {"total_staff_number":1},{"background":true} )
可以通过使副本节点脱机、构建索引并使节点联机(允许节点赶上主副本节点)来在脱机状态下创建索引。
准备好后,我们可以将一个节点升级到主节点,并使另一个辅助节点脱机。
References
- MongoDB Manual, Indexes https://docs.mongodb.com/manual/indexes/.
- Banker K., Bakkum P., Verch S., Garret D., Hawkins T., MongoDB in Action, 2nd ed., Manning Publishers, 2016.