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})

密集索引在以下情况下不方便使用:

  1. unique index on a ?eld that doesn’t appear in every document in a collection is needed.
  2. 集合中的大量文档没有索引键。

在稀疏索引中,只有具有索引键值的文档才被索引:

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. 可以使用索引处理相等查询。
  2. 范围查询不能使用哈希索引。
  3. 不允许使用多键哈希索引。
  4. 浮点值在哈希之前被转换为整数;1.4和1.5在散列索引中具有相同的值。

Geospacial index

Geospacial index允许基于每个文档中存储的纬度和经度值查找靠近给定位置的文档。
Geospacial index可用于有效的计算地理距离,包括地球的曲率。

MongoDB支持不同种类的索引,然而,只有下面列出的前两种索引可以组合为复合索引。

  1. 1: 升序二叉树索引
  2. -1: 降序二叉树索引
  3. “哈希”:哈希表索引;用精确值查找非常快,特别是在非常大的集合中。但不适用于不精确查询(“$ gt”、“$regex”或类似查询)
  4. “文本”:为用自然语言搜索字符串中的单词而设计的文本索引
  5. “2d”:平面上的地理空间索引
  6. “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

  1. MongoDB Manual, Indexes https://docs.mongodb.com/manual/indexes/.
  2. Banker K., Bakkum P., Verch S., Garret D., Hawkins T., MongoDB in Action, 2nd ed., Manning Publishers, 2016.