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中的所有字段都是索引的一部分,

  • 结果中返回的所有字段都在同一索引中。

例如,集合inventorytypeitem字段上具有以下索引:

db.inventory.createIndex( { type: 1, item: 1 } )

该索引将涵盖以下操作,这些操作在typeitem字段上进行查询并仅返回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

对索引字段的限制

分片收集限制

从 MongoDB 3.0 开始,如果索引不包含分片键,则针对mongos运行时,索引不能覆盖sharded集合上的查询,但_id索引具有以下 exception:如果分片集合上的查询仅指定条件在_id字段上并且仅返回_id字段,即使_id字段不是分片键,但针对mongos运行时_id索引也可以覆盖查询。

在以前的版本中,针对mongos运行时,索引不能coversharded集合的查询。

explain

要确定某个查询是否为涵盖查询,请使用db.collection.explain()explain()方法并查看results

db.collection.explain()提供有关其他操作的执行信息,例如db.collection.update()。有关详细信息,请参见db.collection.explain()

有关更多信息,请参见度量 Metrics 使用