Query Optimization查询优化

On this page本页内容

Indexes improve the efficiency of read operations by reducing the amount of data that query operations need to process. 索引通过减少查询操作需要处理的数据量来提高读取操作的效率。This simplifies the work associated with fulfilling queries within MongoDB.这简化了与在MongoDB中实现查询相关的工作。

Create an Index to Support Read Operations创建索引以支持读取操作

If your application queries a collection on a particular field or set of fields, then an index on the queried field or a compound index on the set of fields can prevent the query from scanning the whole collection to find and return the query results. 如果应用程序查询特定字段或字段集上的集合,则查询字段上的索引或字段集上的复合索引可能会阻止查询扫描整个集合以查找和返回查询结果。For more information about indexes, see the complete documentation of indexes in MongoDB.有关索引的更多信息,请参阅MongoDB中索引的完整文档。

Example

An application queries the inventory collection on the type field. 应用程序在type字段上查询inventory集合。The value of the type field is user-driven.type字段的值由用户驱动。

var typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );

To improve the performance of this query, add an ascending or a descending index to the inventory collection on the type field. 要提高此查询的性能,请在type字段的inventory集合中添加升序或降序索引。[1] In mongosh, you can create indexes using the db.collection.createIndex() method:

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

This index can prevent the above query on type from scanning the whole collection to return the results.此索引可以防止上述type上的查询扫描整个集合以返回结果。

To analyze the performance of the query with an index, see Analyze Query Performance.要使用索引分析查询的性能,请参阅分析查询性能

In addition to optimizing read operations, indexes can support sort operations and allow for a more efficient storage utilization. 除了优化读取操作外,索引还可以支持排序操作,并允许更高效的存储利用率。See db.collection.createIndex() and Indexes for more information about index creation.有关索引创建的更多信息,请参阅db.collection.createIndex()索引

[1] For single-field indexes, the selection between ascending and descending order is immaterial. 对于单字段索引,升序和降序之间的选择无关紧要。For compound indexes, the selection is important. 对于复合索引,选择很重要。See indexing order for more details.有关更多详细信息,请参阅索引顺序

Query Selectivity查询选择性

Query selectivity refers to how well the query predicate excludes or filters out documents in a collection. 查询选择性是指查询谓词排除或筛选集合中文档的程度。Query selectivity can determine whether or not queries can use indexes effectively or even use indexes at all.查询选择性可以决定查询是否可以有效地使用索引,甚至可以完全使用索引。

More selective queries match a smaller percentage of documents. 更具选择性的查询匹配的文档比例更小。For instance, an equality match on the unique _id field is highly selective as it can match at most one document.例如,唯一的_id字段上的相等匹配是高度选择性的,因为它最多可以匹配一个文档。

Less selective queries match a larger percentage of documents. 选择性较低的查询匹配的文档比例较高。Less selective queries cannot use indexes effectively or even at all.选择性较差的查询无法有效地使用索引,甚至根本无法使用索引。

For instance, the inequality operators $nin and $ne are not very selective since they often match a large portion of the index. 例如,不等式运算符$nin$ne不是很有选择性,因为它们通常匹配索引的很大一部分。As a result, in many cases, a $nin or $ne query with an index may perform no better than a $nin or $ne query that must scan all documents in a collection.因此,在许多情况下,带有索引的$nin$ne查询的性能可能并不比必须扫描集合中所有文档的$nin$ne查询好。

The selectivity of regular expressions depends on the expressions themselves. 正则表达式的选择性取决于表达式本身。For details, see regular expression and index use.有关详细信息,请参阅正则表达式和索引的使用。

Covered Query覆盖查询

A covered query is a query that can be satisfied entirely using an index and does not have to examine any documents. 覆盖查询是一种完全可以使用索引满足的查询,不必检查任何文档。An index covers a query when all of the following apply:当以下所有条件都适用时,索引会覆盖查询:

  • all the fields in the query are part of an index, and查询中的所有字段都是索引的一部分,并且
  • all the fields returned in the results are in the same index.结果中返回的所有字段都在同一索引中。
  • no fields in the query are equal to null (i.e. {"field" : null} or {"field" : {$eq : null}} ).查询中没有字段等于null(即{"field": null}{"field":{$eq: null})。

For example, a collection inventory has the following index on the type and item fields:例如,inventory库存在typeitem字段上具有以下索引:

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

This index will cover the following operation which queries on the type and item fields and returns only the item field:此索引将涵盖以下操作,该操作查询typeitem字段,并仅返回item字段:

db.inventory.find(
   { type: "food", item:/^c/ },
   { item: 1, _id: 0 }
)

For the specified index to cover the query, the projection document must explicitly specify _id: 0 to exclude the _id field from the result since the index does not include the _id field.为了让指定的索引覆盖查询,投影文档必须显式指定_id:0以从结果中排除_id字段,因为索引不包括_id字段。

Changed in version 3.6.在版本3.6中更改

An index can cover a query on fields within embedded documents. 索引可以覆盖对嵌入文档中字段的查询。[2]

For example, consider a collection userdata with documents of the following form:例如,考虑一个具有以下形式的文档的集合userdata

{ _id: 1, user: { login: "tester" } }

The collection has the following index:该集合具有以下索引:

{ "user.login": 1 }

The { "user.login": 1 } index will cover the query below:{ "user.login": 1 }索引将涵盖以下查询:

db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )
[2] To index fields in embedded documents, use dot notation.要索引嵌入文档中的字段,请使用点符号

Multikey Covering多键覆盖

Starting in 3.6, multikey indexes can cover queries over the non-array fields if the index tracks which field or fields cause the index to be multikey. 从3.6开始,如果索引跟踪导致索引为多键的字段,则多键索引可以覆盖对非数组字段的查询。Multikey indexes created in MongoDB 3.4 or later on storage engines other than MMAPv1 track this data.MongoDB 3.4或更高版本在除MMAPv1之外的存储引擎上创建的多键索引跟踪此数据。

Multikey indexes多键索引 cannot cover queries over array field(s).无法覆盖对数组字段的查询。

Performance表演

Because the index contains all fields required by the query, MongoDB can both match the query conditions and return the results using only the index.由于索引包含查询所需的所有字段,MongoDB既可以匹配查询条件,也可以只使用索引返回结果。

Querying only the index can be much faster than querying documents outside of the index. 仅查询索引可能比查询索引外的文档快得多。Index keys are typically smaller than the documents they catalog, and indexes are typically available in RAM or located sequentially on disk.索引键通常比它们编目的文档小,索引通常在RAM中可用,或按顺序位于磁盘上。

Limitations局限性

Restrictions on Indexed Fields对索引字段的限制

Restrictions on Sharded Collection对分片集合的限制

Starting in MongoDB 3.0, an index cannot cover a query on a sharded collection when run against a mongos if the index does not contain the shard key, with the following exception for the _id index: If a query on a sharded collection only specifies a condition on the _id field and returns only the _id field, the _id index can cover the query when run against a mongos even if the _id field is not the shard key.从MongoDB 3.0开始,在mongos上运行时,如果索引不包含分片键,索引就不能覆盖分片集合上的查询,但_id索引除外:如果对分片集合的查询只指定了_id字段的条件,并且只返回_id字段,在mongos上运行时,_id索引可以覆盖查询,即使_id字段不是分片键。

In previous versions, an index cannot cover a query on a sharded collection when run against a mongos.在以前的版本中,在mongos上运行时,索引不能覆盖分片集合上的查询。

explain

To determine whether a query is a covered query, use the db.collection.explain() or the explain() method and review the results.要确定查询是否为覆盖查询,请使用db.collection.explain()explain()方法并查看结果。

For more information see Measure Index Use.有关更多信息,请参阅度量索引使用

←  Causal Consistency and Read and Write ConcernsEvaluate Performance of Current Operations →