On this page
Query Optimization
在本页面
索引通过减少查询操作需要处理的数据量来提高读取操作的效率。这简化了与在 MongoDB 中实现查询相关的工作。
创建索引以支持读取操作
如果您的应用程序查询特定字段或一组字段上的集合,则查询字段上的索引或该字段集上的compound index可以阻止查询扫描整个集合以查找并返回查询结果。有关索引的更多信息,请参见MongoDB 中索引的完整文档。
Example
应用程序在type
字段上查询inventory
集合。 type
字段的值是用户驱动的。
var typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );
若要提高此查询的性能,请在type
字段的inventory
集合中添加升序或降序索引。 [1]在mongo Shell 中,您可以使用db.collection.createIndex()方法创建索引:
db.inventory.createIndex( { type: 1 } )
此索引可以防止上述对type
的查询扫描整个集合以返回结果。
要分析带有索引的查询的性能,请参阅分析查询性能。
除了优化读取操作外,索引还可以支持排序操作,并可以提高存储利用率。有关创建索引的更多信息,请参见db.collection.createIndex()和Indexes。
[1] | 对于单字段索引,升序和降序之间的选择并不重要。对于复合索引,选择很重要。有关更多详细信息,请参见indexing order。 |
Query Selectivity
查询选择性是指查询谓词排除或过滤出集合中文档的程度。查询选择性可以确定查询是否可以有效使用索引,甚至根本不使用索引。
更具选择性的查询会匹配较小百分比的文档。例如,唯一_id
字段上的相等匹配具有很高的选择性,因为它最多可以匹配一个文档。
选择性较低的查询与较大比例的文档匹配。选择性较低的查询不能有效地使用索引,甚至根本无法使用索引。
例如,不等式运算符$nin和$ne *选择性不高,因为它们经常与索引的大部分匹配。结果,在许多情况下,带有索引的$nin或$ne查询的性能可能不及必须扫描集合中所有文档的$nin或$ne查询。
regular expressions的选择性取决于表达式本身。有关详细信息,请参见正则表达式和索引使用。
Covered Query
涵盖查询是可以完全使用索引满足的查询,而不必检查任何文档。当以下两个条件同时适用时,索引为covers:
query中的所有字段都是索引的一部分, 和
结果中返回的所有字段都在同一索引中。
例如,集合inventory
在type
和item
字段上具有以下索引:
db.inventory.createIndex( { type: 1, item: 1 } )
该索引将涵盖以下操作,这些操作在type
和item
字段上进行查询并仅返回item
字段:
db.inventory.find(
{ type: "food", item:/^c/ },
{ item: 1, _id: 0 }
)
对于指定的索引以覆盖查询,投影文档必须明确指定_id: 0
以从结果中排除_id
字段,因为索引不包含_id
字段。
在版本 3.6 中更改:索引可以涵盖对嵌入式文档中的字段的查询。 [2]
例如,考虑具有以下格式文档的集合userdata
:
{ _id: 1, user: { login: "tester" } }
该集合具有以下索引:
{ "user.login": 1 }
{ "user.login": 1 }
索引将涵盖以下查询:
db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
[2] | 要为嵌入式文档中的字段构建索引,请使用dot notation。 |
Multikey Covering
从 3.6 开始,如果索引跟踪哪个或哪些字段导致索引成为多键,则多键索引可以覆盖非数组字段的查询。在 MongoDB 3.4 或更高版本中在 MMAPv1 以外的存储引擎上创建的多键索引会跟踪此数据。
Multikey indexes无法涵盖对数组字段的查询。
Performance
由于索引包含查询所需的所有字段,因此 MongoDB 既可以匹配query conditions,也可以仅使用索引返回结果。
仅查询索引比查询索引之外的文档要快得多。索引键通常小于它们所分类的文档,并且索引通常在 RAM 中可用,或者 Sequences 位于磁盘上。
Limitations
对索引字段的限制
Multikey indexes无法涵盖对数组字段的查询。
See also
分片收集限制
从 MongoDB 3.0 开始,如果索引不包含分片键,则针对mongos运行时,索引不能覆盖sharded集合上的查询,但_id
索引具有以下 exception:如果分片集合上的查询仅指定条件在_id
字段上并且仅返回_id
字段,即使_id
字段不是分片键,但针对mongos运行时_id
索引也可以覆盖查询。
在以前的版本中,针对mongos运行时,索引不能cover对sharded集合的查询。
explain
要确定某个查询是否为涵盖查询,请使用db.collection.explain()或explain()方法并查看results。
db.collection.explain()提供有关其他操作的执行信息,例如db.collection.update()。有关详细信息,请参见db.collection.explain()。
有关更多信息,请参见度量 Metrics 使用。