Query optimization improves the efficiency of read operations by reducing the amount of data that query operations need to process. Use indexes, projections, and query limits to enhance query performance and reduce resource consumption.查询优化通过减少查询操作需要处理的数据量来提高读取操作的效率。使用索引、投影和查询限制来提高查询性能并减少资源消耗。
Query optimization can occur both during development and later as your data usage and demand changes. As collections grow, a periodic review of query performance can help determine when clusters need to scale up or scale out.查询优化可以在开发过程中进行,也可以在以后随着数据使用和需求的变化而进行。随着集合的增长,定期检查查询性能可以帮助确定集群何时需要扩展或向外扩展。
Create Indexes to Support Queries创建索引以支持查询
Indexes store values from individual fields or sets of fields from a collection in a separate data structure. In read operations, they allow MongoDB to search in the index to identify relevant documents instead of the entire collection. In write operations, MongoDB must both write the change to the collection and update the index.索引将单个字段或集合中的字段集的值存储在单独的数据结构中。在读取操作中,它们允许MongoDB在索引中搜索以识别相关文档,而不是整个集合。在写操作中,MongoDB必须将更改写入集合并更新索引。
Create indexes for commonly issued queries. If a query searches multiple fields, create a compound index.为常见查询创建索引。如果查询搜索多个字段,请创建复合索引。
For example, consider the following query on the 例如,考虑对type field in the inventory collection:inventory集合中的type字段进行以下查询:
let typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );
To improve performance for this query, add an index to the 为了提高此查询的性能,请在inventory collection on the type field. inventory集合中的type字段添加索引。[1] In 在mongosh, create indexes using the db.collection.createIndex() method:mongosh中,使用db.collection.createIndex()方法创建索引:
db.inventory.createIndex( { type: 1 } )
To analyze query performance, see Interpret Explain Plan Results.要分析查询性能,请参阅解释计划结果。
| [1] | |
Create Selective Queries创建选择性查询
Query selectivity refers to how well the query predicate filters out documents in a collection. Query selectivity determines whether queries can use indexes effectively.查询选择性是指查询谓词筛选集合中文档的能力。查询选择性决定了查询是否可以有效地使用索引。
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 and cannot use indexes effectively.选择性较低的查询会匹配更大比例的文档,并且无法有效地使用索引。
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.
Project Only Necessary Data仅项目所需数据
When you need a subset of fields from documents, you can improve performance by returning only the fields you need. Projections reduce network traffic and processing time.当您需要文档中的字段子集时,可以通过仅返回所需的字段来提高性能。预测减少了网络流量和处理时间。
For example, if your query to the 例如,如果您对posts collection needs only the timestamp, title, author, and abstract fields, specify those fields in the projection:posts集合的查询只需要timestamp、title、author和abstract字段,请在投影中指定这些字段:
db.posts.find(
{},
{ timestamp : 1, title : 1, author : 1, abstract : 1}
).sort( { timestamp : -1 } )
When you use a 当您使用$project aggregation stage it should typically be the last stage in your pipeline, used to specify which fields to return to the client.$project聚合阶段时,它通常应该是管道中的最后一个阶段,用于指定要返回给客户端的字段。
Using a 在管道的开始或中间使用$project stage at the beginning or middle of a pipeline to reduce the number of fields passed to subsequent pipeline stages is unlikely to improve performance, because the database performs this optimization automatically.$project阶段来减少传递给后续管道阶段的字段数量不太可能提高性能,因为数据库会自动执行此优化。
For more information on using projections, see Project Fields to Return from Query.有关使用投影的更多信息,请参阅从查询返回的项目字段。
Example示例
To achieve a covered query, you must index projected fields. The ESR (Equality, Sort, Range) rule applies to the order of fields in the index.要实现覆盖查询,您必须对投影字段进行索引。ESR(相等、排序、范围)规则适用于索引中字段的顺序。
For example, consider the following index on an 例如,考虑以下inventory collection:inventory集合索引:
db.inventory.createIndex( { type: 1, _id: 1, price: 1, item: 1, expiryDate: 1} )
The above query, while technically correct, is not structured to optimize query performance.上述查询虽然在技术上是正确的,但其结构并不是为了优化查询性能。
The following query uses the ESR (Equality, Sort, Range) rule to create a more efficient compound index and improve query response times.以下查询使用ESR(相等、排序、范围)规则来创建更有效的复合索引并缩短查询响应时间。
db.inventory.aggregate([
{ $match: {type: "food", expiryDate: { $gt: ISODate("2025-07-10T00:00:00Z") }}},
{ $sort: { item: 1 }},
{ $project: { _id: 1, price: 1} }
])
The index and query follow the ESR rule:索引和查询遵循ESR规则:
typeis used for an equality match (E), so it is the first field in the index.type用于相等匹配(E),因此它是索引中的第一个字段。itemis used for sorting (S), so it is aftertypein the index.item用于排序(S),因此它位于索引中的type之后。expiryDateis used for a range query (R), so it is the last field in the index.expiryDate用于范围查询(R),因此它是索引中的最后一个字段。
Limit Query Results限制查询结果
MongoDB cursors return results in batches. If you know the number of results you want, specify that value in the MongoDB游标分批返回结果。如果你知道你想要的结果数量,在limit() method. Limiting results reduces the demand on network resources.limit()方法中指定该值。限制结果减少了对网络资源的需求。
Generally, limiting results is most useful when results are sorted so you know which documents will be returned. For example, if you need only 10 results from your query to the 通常,当对结果进行排序时,限制结果是最有用的,这样您就知道将返回哪些文档。例如,如果您对posts collection, run the following query:posts集合的查询只需要10个结果,请运行以下查询:
db.posts.find().sort( { timestamp : -1 } ).limit(10)
For more information on limiting results, see 有关限制结果的更多信息,请参阅limit().limit()。
Use Index Hints使用索引提示
The query optimizer typically selects the optimal index for a specific operation. However, you can force MongoDB to use a specific index using the 查询优化器通常为特定操作选择最佳索引。但是,您可以使用hint() method. hint()方法强制MongoDB使用特定的索引。Use 使用hint() to support performance testing or when you are querying a field that appears in several indexes to guarantee that MongoDB uses the correct index.hint()支持性能测试,或者当您查询出现在多个索引中的字段时,以确保MongoDB使用正确的索引。
Use Server-Side Operations使用服务器端操作
Use MongoDB's 使用MongoDB的$inc operator to increment or decrement values in documents. $inc运算符来增加或减少文档中的值。The operator increments the value of the field on the server side, as an alternative to selecting a document, making simple modifications in the client, and then writing the entire document to the server. 运算符在服务器端递增字段的值,作为选择文档、在客户端进行简单修改,然后将整个文档写入服务器的替代方法。The $inc operator can also help avoid race conditions that occur when two application instances query for a document, manually increment a field, and save the entire document back at the same time.$inc运算符还可以帮助避免两个应用程序实例查询文档、手动增加字段并同时将整个文档保存回时出现的竞争条件。
Run Covered Queries运行覆盖查询
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 (both as specified by the application and as needed internally such as for sharding purposes) are part of an index.查询中的所有字段(包括应用程序指定的字段和内部需要的字段,例如用于分片的字段)都是索引的一部分。All the fields returned in the results are in the same index.结果中返回的所有字段都在同一索引中。No fields in the query are equal to查询中没有字段等于null. For example, the following query predicates cannot result in covered queries:null。例如,以下查询谓词不能导致覆盖查询:{ "field": null }{ "field": { $eq: null } }
Example示例
An inventory collection has the following index on the type and item fields:inventory集合在type和item字段上具有以下索引:
db.inventory.createIndex( { type: 1, item: 1 } )
The index covers the following operation which queries on the 该索引涵盖了以下操作,该操作查询type and item fields and returns only the item field:type和item字段并仅返回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字段。
Embedded Documents嵌入式文档
An index can cover a query on fields within embedded documents.索引可以覆盖对嵌入式文档中字段的查询。
For example, consider a 例如,考虑一个userdata collection with documents of the following form:userdata集合,其中包含以下形式的文档:
db.userdata.insertOne(
{ _id: 1, user: { login: "tester" } }
)
The collection has the following index:该集合具有以下索引:
db.userdata.createIndex(
{ "user.login": 1 }
)
The { "user.login": 1 } index covers the following query:{ "user.login": 1 }索引包含以下查询:
db.userdata.find(
{ "user.login": "tester" },
{ "user.login": 1, _id: 0 }
)
Note
To index fields in embedded documents, use dot notation. See Create an Index on an Embedded Field.要为嵌入式文档中的字段建立索引,请使用点符号。请参见在嵌入式字段上创建索引。
Multikey Covering多键覆盖
Multikey indexes can cover queries over the non-array fields if the index tracks which field or fields cause the index to be multikey.如果索引跟踪哪个或哪些字段导致索引是多键的,则多键索引可以覆盖对非数组字段的查询。
Multikey indexes cannot cover queries over array fields.多键索引不能覆盖数组字段上的查询。
For an example of a covered query with a multikey index, see Covered Queries on the multikey indexes page.有关具有多键索引的覆盖查询的示例,请参阅多键索引页面上的覆盖查询。
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局限性
Index Types索引类型
Not all index types can cover queries. For details on covered index support, refer to the documentation page for the corresponding index type.并非所有索引类型都能覆盖查询。有关覆盖索引支持的详细信息,请参阅相应索引类型的文档页面。
Sharded Collections分片化集合
When run on 在mongos, indexes can only cover queries on sharded collections if the index contains the shard key.mongos上运行时,如果索引包含分片键,则索引只能覆盖对分片集合的查询。
Explain Results解释结果
To determine whether a query is a covered query, use the 要确定查询是否为覆盖查询,请使用db.collection.explain() or the explain() method. db.collection.explain()或explain()方法。See Covered Queries.请参阅涵盖的查询。