MongoDB 索引详解(一)

  • 默认_id 索引
  • 创建索引
  • 索引类型
  • 索引属性
  • 索引使用
  • 索引及排序规则
  • 覆盖查询
  • 交叉索引
  • 限制
  • 其他注意事项

索引支持MongoDB中查询的高效执行。如果没有索引,MongoDB必须执行集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。如果查询存在适当的索引,MongoDB可以使用索引来限制它必须检查的文档数。

索引是特殊的数据结构[1],它以易于遍历的形式存储部分集合数据集。索引存储特定字段或字段集的值,按字段值排序。索引条目的排序支持高效的等值匹配和基于范围的查询操作。此外,MongoDB可以使用索引中的顺序返回排序后结果。

下图说明了查询如何使用索引选择和排序相匹配文档:

1

从根本上说,MongoDB中的索引与其他数据库系统中的索引类似。MongoDB在集合级别定义索引,并支持MongoDB集合中文档的任何字段或子字段定义索引。

默认_id 索引

MongoDB 在创建集合期间在_id字段上创建了唯一索引。该索引可防止客户端插入两个_id字段值相同的文档。_id字段的索引不能删除。

注意
在分片群集中,如果不将该_id字段用作分片键,则应用程序必须确保_id字段值的唯一性以防止出错。通常使用标准的自动生成的ObjectId来完成。

创建索引

===Mongo shell

使用db.collection.createIndex()

db.collection.createIndex( , )

例如创建单个键上的降序索引

db.collection.createIndex( { name: -1 } )

db.collection.createIndex方法仅用于创建索引,且相同定义的索引不存在

[1] MongoDB 索引使用B-tree数据结构

索引类型

MongoDB提供了许多不同的索引类型来支持特定类型的数据和查询。
单字段索引:除MongoDB定义的_id索引外,MongoDB还支持在文档的单个字段上创建用户定义的升序/降序索引。

2

对于单字段索引和排序操作,索引键的排序顺序(即升序或降序)无关紧要,因为MongoDB可以在任一方向上遍历索引。

有关单字段索引的详细信息,请参阅单字段索引和单字段索引排序。

==复合索引

MongoDB支持用户在多个字段上定义索引,即 复合索引。

复合索引中字段的顺序很重要。例如,如果复合索引为{ userid: 1, score: -1 },则索引首先以userid字段进行排序,然后在每个userid 值以score字段进行排序。

3

对于复合索引和排序操作,索引键的排序顺序(即升序或降序)可以确定索引是否可以支持排序操作。有关索引顺序对复合索引中结果的影响的详细信息,请参阅 排序顺序。

有关复合索引的详细信息,请参阅复合索引和多个字段排序。

==多键索引

MongoDB使用多键索引来索引存储在数组中的内容。如果索引字段包含数组值,MongoDB会为数组的每个元素创建单独的索引条目。这些多键索引允许查询通过匹配数组中的元素来获取包含数组的文档。如果索引字段包含数组值,MongoDB会自动决定是否需要创建多键索引; 不需要显式指定多键类型。

4

多键索引和多键索引边界 获取有关多键索引的详细信息。

==地理空间索引

为了支持对地理空间坐标数据的高效查询,MongoDB提供了两个特殊索引:返回结果时使用平面几何的2d索引和使用球面几何的2dphere索引。

有关地理空间索引的更多介绍,请参阅2d Index Internals。

== 文本索引

MongoDB提供了一种text索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停用词(例如“the”,“a”,“or”),并且集合中的词干均仅存储词根。
有关文本索引和搜索的详细信息,请参阅文本索引。

== 哈希索引

为了支持基于哈希的分片,MongoDB提供了哈希索引类型,索引字段值的哈希值。这些索引在其范围内具有更随机的值分布,但仅 支持等值匹配且不支持范围查询。

索引属性

==唯一索引

索引的唯一属性会导致MongoDB拒绝索引字段的重复值。除了唯一约束之外,唯一索引在功能上可与其他MongoDB索引互换。

==部分索引

3.2版本的新功能。

部分索引仅索引符合特定的过滤表达式的集合中的文档。通过索引集合中的文档子集,部分索引具有较低的存储要求,减少索引创建和维护的性能成本

部分索引是稀疏索引功能的超集,应该优先于稀疏索引。

==稀疏索引

索引的稀疏属性可确保索引仅包含具有索引字段的文档的条目。索引会跳过没有索引字段的文档。

将稀疏索引与唯一索引组合,以拒绝具有字段重复值的文档,但忽略没有索引键的文档。

==TTL索引

TTL索引是MongoDB在指定时间后自动从集合中删除文档的特殊索引。这是某些类型的信息理想选择,例如机器生成的事件数据,日志和会话信息,这些信息只需要在数据库中保存有限的时间。

请参阅通过设置TTL过期集合中的数据。

索引使用

索引可以提高读操作的效率。 分析查询性能教程提供有和没有索引的查询的执行统计信息的示例。

有关MongoDB如何选择要使用的索引,请参阅查询优化器。

索引和排序规则

3.4版本的新功能
排序规则允许用户为字符串比较指定特定于语言的规则,例如字母和重音标记。

===Mongo Shell

使用索引进行字符串比较,操作同时指定相同的排序规则。也就是说,如果操作指定了不同的排序规则,则具有排序规则的索引,不支持对索引字段执行字符串比较的操作。

例如,集合myColl在字符串字段category存在索引,该索引的排序规则locale 为”fr”,即以法语进行升序排序。

db.myColl.createIndex( { category: 1 }, { collation: { locale: “fr” } } )

以下查询操作(指定与索引相同的排序规则)可以使用索引:

db.myColl.find( { category: “cafe” } ).collation( { locale: “fr” } )

但是,以下查询操作(默认情况下使用“简单”二进制排序规则)无法使用索引:

db.myColl.find( { category: “cafe” } )

对于索引前缀键不是字符串,数组和嵌入文档的复合索引,指定不同排序规则仍然可以使用索引前缀键的索引进行比较。
例如,集合myColl在数值字段score和price及字符串category上有复合索引; 使用以排序规则locale为”fr”进行字符串比较:

db.myColl.createIndex({ score: 1, price: 1, category: 1 },{ collation: { locale: “fr” } })

以下操作使用”simple”二进制排序规则进行字符串比较,可以使用索引:

db.myColl.find( { score: 5 } ).sort( { price: 1 } )
db.myColl.find( { score: 5, price: { $gt: NumberDecimal( “10″ ) } } ).sort( { price: 1 } )

以下操作使用”simple”二进制排序规则对索引category字段进行字符串比较,可以使用索引仅满足部分查询:score: 5

db.myColl.find( { score: 5, category: “cafe” } )

有关排序规则的详细信息,请参阅排序规则详情页面。

以下索引仅支持简单的二进制比较规则,不支持排序规则:

文本索引,2d索引,和geoHaystack索引

覆盖查询

当查询标准和查询投影仅包含索引字段,MongoDB的可以直接从索引返回结果,无需扫描的任何文档或文档加载到内存。这些覆盖的查询可以非常有效。

5

有关覆盖查询的更多信息,请参阅 覆盖查询。

交叉索引

2.6版中的新功能。

MongoDB可以使用交叉索引来完成查询。对于指定复合查询条件的查询,如果一个索引可以满足查询条件的一部分,而另一个索引可以满足查询条件的另一部分,则MongoDB可以使用两个索引的交集来完成查询。使用复合索引还是使用索引交集更有效取决于具体的查询和系统。
有关索引交集的详细信息,请参见索引交点。

限制

某些限制适用于索引,例如索引键的长度或每个集合的索引数。有关详细信息,请参阅索引限制。

其他注意事项

虽然索引可以提高查询性能,但索引也提出了一些操作注意事项 有关详细信息,请参阅索引的操作注意事项。
如果您的集合包含大量数据,并且您的应用程序需要能够在创建索引时访问数据,请考虑在后台构建索引。
要为副本集构建或重建索引,请参阅在副本集上构建索引。
某些驱动程序可以使用NumberLong(1)而不是 1作为条件来指定索引。这对索引结果没有任何影响。

原文链接:https://docs.mongodb.com/manual/indexes/
译者:莫微
DBA一枚,关注数据库发展,愿为之添砖加瓦。

发表评论