Docs HomeMongoDB Manual

Analyze Query Performance分析查询性能

The explain plan results for queries are subject to change between MongoDB versions.查询的解释计划结果可能会在MongoDB版本之间发生变化。

The cursor.explain("executionStats") and the db.collection.explain("executionStats") methods provide statistics about the performance of a query. cursor.explain("executionStats")db.collection.explain("executionStats")方法提供有关查询性能的统计信息。These statistics can be useful in measuring if and how a query uses an index. See db.collection.explain() for details.这些统计信息在衡量查询是否使用索引以及如何使用索引时非常有用。有关详细信息,请参阅db.collection.explain()

MongoDB Compass provides an Explain Plan tab, which displays statistics about the performance of a query. MongoDB Compass提供了一个解释计划选项卡,其中显示了有关查询性能的统计信息。These statistics can be useful in measuring if and how a query uses an index.这些统计信息在衡量查询是否使用索引以及如何使用索引时非常有用。

Evaluate the Performance of a Query评估查询的性能

Consider a collection inventory with the following documents:考虑一个包含以下文档的集合inventory

{ "_id" : 1, "item" : "f1", type: "food", quantity: 500 }
{ "_id" : 2, "item" : "f2", type: "food", quantity: 100 }
{ "_id" : 3, "item" : "p1", type: "paper", quantity: 200 }
{ "_id" : 4, "item" : "p2", type: "paper", quantity: 150 }
{ "_id" : 5, "item" : "f3", type: "food", quantity: 300 }
{ "_id" : 6, "item" : "t1", type: "toys", quantity: 500 }
{ "_id" : 7, "item" : "a1", type: "apparel", quantity: 250 }
{ "_id" : 8, "item" : "a2", type: "apparel", quantity: 400 }
{ "_id" : 9, "item" : "t2", type: "toys", quantity: 50 }
{ "_id" : 10, "item" : "f4", type: "food", quantity: 75 }

The documents appear in MongoDB Compass as the following:文档在MongoDB Compass中显示如下:

Compass Inventory collection documents

Query with No Index无索引查询

The following query retrieves documents where the quantity field has a value between 100 and 200, inclusive:以下查询检索quantity字段值介于100200之间(包括100200)的文档:

db.inventory.find( { quantity: { $gte: 100, $lte: 200 } } )

The query returns the following documents:查询返回以下文档:

{ "_id" : 2, "item" : "f2", "type" : "food", "quantity" : 100 }
{ "_id" : 3, "item" : "p1", "type" : "paper", "quantity" : 200 }
{ "_id" : 4, "item" : "p2", "type" : "paper", "quantity" : 150 }

To view the query plan selected, chain the cursor.explain("executionStats") cursor method to the end of the find command:要查看所选的查询计划,请将cursor.explain("executionStats")游标方法链接到find命令的末尾:

db.inventory.find(
{ quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")

explain() returns the following results:返回以下结果:

{
queryPlanner: {
...
winningPlan: {
queryPlan: {
stage: 'COLLSCAN',
...
}
}
},
executionStats: {
executionSuccess: true,
nReturned: 3,
executionTimeMillis: 0,
totalKeysExamined: 0,
totalDocsExamined: 10,
executionStages: {
stage: 'COLLSCAN',
...
},
...
},
...
}
  • queryPlanner.winningPlan.queryPlan.stage displays COLLSCAN to indicate a collection scan.显示COLLSCAN以指示集合扫描。

    Collection scans indicate that the mongod had to scan the entire collection document by document to identify the results. 集合扫描表明mongod必须逐个文档扫描整个集合文档才能识别结果。This is a generally expensive operation and can result in slow queries.这通常是一个昂贵的操作,并且可能导致查询速度缓慢。

  • executionStats.nReturned displays 3 to indicate that the query matches and returns three documents.显示3表示查询匹配并返回三个文档。

  • executionStats.totalKeysExamined displays 0 to indicate that this is query is not using an index.显示0表示此查询未使用索引。

  • executionStats.totalDocsExamined displays 10 to indicate that MongoDB had to scan ten documents (i.e. all documents in the collection) to find the three matching documents.显示10表示MongoDB必须扫描十个文档(即集合中的所有文档)才能找到三个匹配的文档。

The following query retrieves documents where the quantity field has a value between 100 and 200, inclusive:以下查询检索quantity字段值介于100200之间(包括100200)的文档:

Copy the following filter into the Compass query bar and click Find:将以下筛选器复制到Compass查询栏中,然后单击“查找”:

{ quantity: { $gte: 100, $lte: 200 } }

The query returns the following documents:查询返回以下文档:

Compass no index query results

To view the query plan selected:查看所选查询计划:

  1. Click the Explain Plan tab for the test.inventory collection.单击test.inventory集合的“解释计划”选项卡。

  2. Click Explain.单击“解释”。

MongoDB Compass displays the query plan as follows:MongoDB Compass显示查询计划如下:

Compass no index query plan
Note

Because we are working with such a small dataset for the purposes of this tutorial, the Actual Query Execution Time displays 0 seconds, even though we are not using an index.因为为了本教程的目的,我们使用的是一个如此小的数据集,所以“实际查询执行时间”显示为0秒,即使我们没有使用索引。

In a larger dataset, the difference in query execution time between an indexed query versus a non-indexed query would be much more substantial.在更大的数据集中,索引查询和非索引查询之间的查询执行时间差异会更大。

Visual Tree可视化树

  • The Query Performance Summary shows the execution stats of the query:“查询性能摘要”显示查询的执行统计信息:

    • Documents Returned displays 3 to indicate that the query matches and returns three documents.“返回的文档”显示3,表示查询匹配并返回三个文档。

    • Index Keys Examined displays 0 to indicate that this query is not using an index.“已检查的索引键”显示0,表示此查询未使用索引。

    • Documents Examined displays 10 to indicate that MongoDB had to scan ten documents (i.e. all documents in the collection) to find the three matching documents.“已检查的文档”显示10,表示MongoDB必须扫描10个文档(即集合中的所有文档)才能找到三个匹配的文档。

  • Below the Query Performance Summary, MongoDB Compass displays the COLLSCAN query stage to indicate that a collection scan was used for this query.在“查询性能摘要”下面,MongoDB Compass显示COLLSCAN查询阶段,以指示此查询使用了集合扫描。

    Collection scans indicate that the mongod had to scan the entire collection document by document to identify the results. This is a generally expensive operation and can result in slow queries.集合扫描表明mongod必须逐个文档扫描整个集合文档才能识别结果。这通常是一个昂贵的操作,并且可能导致查询速度缓慢。

Raw JSON

The explain details can also be viewed in raw JSON format by clicking Raw JSON below the query bar:还可以通过单击查询栏下方的“Raw JSON”以原始JSON格式查看解释详细信息:

Compass no index query plan raw JSON

The difference between the number of matching documents and the number of examined documents may suggest that, to improve efficiency, the query might benefit from the use of an index.匹配文档的数量和检查文档的数量之间的差异可能表明,为了提高效率,查询可能受益于索引的使用。

Query with Index带索引的查询

To support the query on the quantity field, add an index on the quantity field:要支持对quantity字段的查询,请在quantity字段上添加索引:

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

To view the query plan statistics, use the explain() method:要查看查询计划统计信息,请使用explain()方法:

db.inventory.find(
{ quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")

The explain() method returns the following results:explain()方法返回以下结果:

{
queryPlanner: {
...
winningPlan: {
queryPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
quantity: 1
},
...
}
}
},
rejectedPlans: [ ]
},
executionStats: {
executionSuccess: true,
nReturned: 3,
executionTimeMillis: 0,
totalKeysExamined: 3,
totalDocsExamined: 3,
executionStages: {
...
},
...
},
...
}
  • queryPlanner.winningPlan.queryPlan.inputStage.stage displays IXSCAN to indicate index use.显示IXSCAN以指示索引的使用。

  • executionStats.nReturned displays 3 to indicate that the query matches and returns three documents.显示3表示查询匹配并返回三个文档。

  • executionStats.totalKeysExamined displays 3 to indicate that MongoDB scanned three index entries. 显示3表示MongoDB扫描了三个索引条目。The number of keys examined match the number of documents returned, meaning that the mongod only had to examine index keys to return the results. 检查的键数与返回的文档数相匹配,这意味着mongod只需检查索引键即可返回结果。The mongod did not have to scan all of the documents, and only the three matching documents had to be pulled into memory. mongod不必扫描所有文档,只需将三个匹配的文档提取到内存中。This results in a very efficient query.这将产生一个非常高效的查询。

  • executionStats.totalDocsExamined display 3 to indicate that MongoDB scanned three documents.显示3表示MongoDB扫描了三个文档。

  1. Click the Indexes tab for the test.inventory collection.单击test.inventory集合的“索引”选项卡。

  2. Click Create Index.单击“创建索引”。

  3. Select quantity from the Select a field name dropdown.从“选择字段名称”下拉列表中选择quantity

  4. Select 1 (asc) from the type dropdown.从类型下拉列表中选择1 (asc)

  5. Click Create.单击“创建”。

Create inventory index in Compass
Note

Leaving the index name field blank causes MongoDB Compass to create a default name for the index.将索引名称字段留空会导致MongoDB Compass为索引创建默认名称。

You can now see your newly created index in the Indexes tab:现在,您可以在“索引”选项卡中查看新创建的索引:

Compass show new index

Return to the Explain Plan tab for the inventory collection and re-run the query from the previous step:返回inventory集合的“解释计划”选项卡,然后重新运行上一步骤中的查询:

{ quantity: { $gte: 100, $lte: 200 } }

MongoDB Compass displays the query plan as follows:MongoDB Compass显示查询计划如下:

Compass explain plan with index

Visual Tree可视化树

  • The Query Performance Summary shows the execution stats of the query:“查询性能摘要”显示查询的执行统计信息:

    • Documents Returned displays 3 to indicate that the query matches and returns three documents.“返回的文档”显示3,表示查询匹配并返回三个文档。

    • Index Keys Examined displays 3 to indicate that MongoDB scanned three index entries. “已检查的索引键”显示3,表示MongoDB扫描了三个索引条目。The number of keys examined match the number of documents returned, meaning that the mongod only had to examine index keys to return the results. 检查的键数与返回的文档数相匹配,这意味着mongod只需检查索引键即可返回结果。The mongod did not have to scan all of the documents, and only the three matching documents had to be pulled into memory. mongod不必扫描所有文档,只需将三个匹配的文档提取到内存中。This results in a very efficient query.这将产生一个非常高效的查询。

    • Documents Examined displays 3 to indicate that MongoDB scanned three documents.“已检查的文档”显示3,表示MongoDB扫描了三个文档。

    • On the right-hand side of the Query Performance Summary, MongoDB Compass shows that the query used the quantity index.在“查询性能摘要”的右侧,MongoDB Compass显示查询使用了quantity索引。

  • Below the Query Performance Summary, MongoDB Compass displays the query stages FETCH and IXSCAN. 在“查询性能摘要”下面,MongoDB Compass显示查询阶段FETCHIXSCANIXSCAN indicates that the mongod used an index to satisfy the query before executing the FETCH stage and retrieving the documents.IXSCAN表示mongod在执行FETCH阶段和检索文档之前使用了一个索引来满足查询。

Raw JSON

The explain details can also be viewed in raw JSON format by clicking Raw JSON below the query bar:还可以通过单击查询栏下方的“Raw JSON”以原始JSON格式查看解释详细信息:

Compass query plan with index raw JSON

Without the index, the query would scan the whole collection of 10 documents to return 3 matching documents. 如果没有索引,查询将扫描10个文档的整个集合,以返回3个匹配的文档。The query also had to scan the entirety of each document, potentially pulling them into memory. 查询还必须扫描每个文档的全部内容,这可能会将它们拉入内存。This results in an expensive and potentially slow query operation.这会导致昂贵且可能较慢的查询操作。

When run with an index, the query scanned 3 index entries and 3 documents to return 3 matching documents, resulting in a very efficient query.当使用索引运行时,查询扫描了3个索引条目和3个文档以返回3个匹配的文档,从而实现了非常高效的查询。