解释结果
本页内容
返回信息查询计划和执行统计的查询计划,MongoDB 提供以下方法
有关重要解释结果字段及其解释方法的信息,请参阅解释解释计划结果。
重要
explain
不考虑查询缓存。相反,它生成一系列候选计划,并选择一个获胜者而不咨询查询缓存。此外,explain
还阻止 MongoDB 查询规划器缓存获胜的计划。
注意
本页仅显示最重要的输出字段,内部使用字段未进行文档说明。输出中列出的字段可能发生变化。
Explain 输出结构
explain
结果以阶段树的格式呈现查询计划。输出结构可能根据所使用的查询引擎而有所不同。操作可以使用经典查询引擎或基于槽位的执行查询引擎。
要了解两种执行引擎之间的输出结构如何不同,请参阅以下示例
winningPlan: { stage: <STAGE1>, ... inputStage: { stage: <STAGE2>, ... inputStage: { stage: <STAGE3>, ... } } },
winningPlan: { queryPlan: { stage: <STAGE1>, ... inputStage: { stage: <STAGE2>, ... inputStage: { stage: <STAGE3>, ... } } } slotBasedPlan: { ... } },
每个阶段都将其结果文档或索引键传递给父节点。叶子节点访问集合或索引。内部节点使用子节点生成的文档或索引键。根节点表示 MongoDB 最终从中推导出结果集的阶段。
阶段描述操作。例如
COLLSCAN
用于集合扫描IXSCAN
用于扫描索引键FETCH
用于检索文档GROUP
用于分组文档SHARD_MERGE
用于合并分片的结果SHARDING_FILTER
用于从分片中过滤出孤立文档TS_MODIFY
用于修改时间序列集合BATCHED_DELETE
用于内部批量处理的多个文档删除(从 MongoDB 6.1 版本开始)EXPRESS
阶段用于有限的一组查询,可以绕过常规查询规划以使用优化的索引扫描计划 (8.0 版本新增。)EXPRESS
阶段可以是以下之一EXPRESS_CLUSTERED_IXSCAN
EXPRESS_DELETE
EXPRESS_IXSCAN
EXPRESS_UPDATE
解释 MongoDB 5.1 及更高版本的解释输出
本节显示了 MongoDB 5.1 及更高版本的 explain
输出。要查看旧版本 MongoDB 的 explain 输出,请参阅该版本的文档。
queryPlanner
explain.queryPlanner
信息详细说明了查询优化器选择的计划。
这些示例可能结合了MongoDB经典和基于槽位的执行引擎的输出结构。它们并不代表所有情况。您的输出可能会有很大差异。
对于非分片集合,explain
返回以下queryPlanner
信息
queryPlanner: { namespace: <string>, indexFilterSet: <boolean>, parsedQuery: { ... }, planCacheShapeHash: <hexadecimal string>, planCacheKey: <hexadecimal string>, maxIndexedOrSolutionsReached: <boolean>, maxIndexedAndSolutionsReached: <boolean>, maxScansToExplodeReached: <boolean>, winningPlan: { stage: <STAGE1>, inputStage: { stage: <string>, ... } }, rejectedPlans: [ <candidate plan1>, ] }
从MongoDB 8.0版本开始,原有的queryHash
字段重命名为planCacheShapeHash
。如果您使用的是早期版本的MongoDB,您将看到queryHash
而不是planCacheShapeHash
。
对于分片集合,explain
在shards
字段中包含每个访问分片的核心查询计划和服务信息
{ queryPlanner: { mongosPlannerVersion: <int> winningPlan: { stage: <STAGE1>, shards: [ { shardName: <string>, connectionString: <string>, serverInfo: { ... }, namespace: <string>, indexFilterSet: <boolean>, parsedQuery: { ... }, querySettings: { ... }, planCacheShapeHash: <hexadecimal string>, planCacheKey: <hexadecimal string>, maxIndexedOrSolutionsReached: <boolean>, maxIndexedAndSolutionsReached: <boolean>, maxScansToExplodeReached: <boolean>, winningPlan: { stage: <STAGE1>, inputStage: { stage: <string>, ... } }, rejectedPlans: [ <candidate plan1>, ] } ] } } }
从MongoDB 8.0版本开始,原有的queryHash
字段重命名为planCacheShapeHash
。如果您使用的是早期版本的MongoDB,您将看到queryHash
而不是planCacheShapeHash
。
explain.queryPlanner
包含有关查询优化器选择查询计划的信息。
explain.queryPlanner.namespace
一个字符串,指定了由查询访问的数据库和集合的命名空间。命名空间的格式为
<database>.<collection>
。
explain.queryPlanner.querySettings
如果设置了查询设置,则
querySettings
包含应用于查询形状的查询设置的详细信息。要添加查询设置并探索示例,包括具有
querySettings
的explain()
输出,请参阅setQuerySettings
。新增在版本中8.0.
explain.queryPlanner.planCacheShapeHash
从MongoDB 8.0版本开始,原有的
queryHash
字段重命名为planCacheShapeHash
。如果您使用的是早期版本的MongoDB,您将看到queryHash
而不是planCacheShapeHash
。一个表示计划缓存查询形状哈希值的十六进制字符串,且仅依赖于计划缓存查询形状。
planCacheShapeHash
可以帮助识别具有相同计划缓存查询形状的慢查询(包括写操作的查询过滤器)。注意
与任何哈希函数一样,两个不同的计划缓存查询形状可能会导致相同的哈希值。然而,不同计划缓存查询形状之间的哈希冲突发生可能性很低。
有关
planCacheShapeHash
和planCacheKey
的更多信息,请参阅 planCacheShapeHash 和 planCacheKey。
explain.queryPlanner.planCacheKey
与查询关联的计划缓存条目的键的哈希值。
与
explain.queryPlanner.planCacheShapeHash
不同,explain.queryPlanner.planCacheKey
是计划缓存查询形状和该形状当前可用索引的函数。具体来说,如果可以支持查询形状的索引被添加或删除,则planCacheKey
的值可能会更改,但planCacheShapeHash
的值不会更改。有关
planCacheShapeHash
和planCacheKey
的更多信息,请参阅 planCacheShapeHash 和 planCacheKey。
explain.queryPlanner.optimizationTimeMillis
查询优化所花费的时间(以毫秒为单位)。此结果不包括优化内部
$lookup
查询所花费的时间。新增在版本中8.0.
explain.queryPlanner.optimizedPipeline
一个布尔值,表示整个聚合管道操作已被优化,并通过查询计划执行阶段的树来实现。
例如,以下聚合操作可以通过查询计划执行树来实现,而不是使用聚合管道。
db.example.aggregate([ { $match: { someFlag: true } } ] ) 该字段仅在值为
true
时存在,并且仅适用于对聚合管道操作的说明。当true
时,因为管道已被优化,输出中不会出现聚合阶段信息。
explain.queryPlanner.winningPlan.stage
一个字符串,表示阶段的名称。
每个阶段都包含与阶段相关的特定信息。例如,一个
IXSCAN
阶段包含索引范围以及其他与索引扫描相关的数据。如果一个阶段有一个或多个子阶段,则该阶段将有一个inputStage
或inputStages
。如果使用了经典查询执行引擎,则该字段会出现。
explain.queryPlanner.winningPlan.inputStages
描述子阶段的文档数组。子阶段向父阶段提供文档或索引键。如果父阶段有多个子节点,则存在该字段。例如,用于 $or 表达式 的阶段可能从多个源获取输入。
如果使用了经典查询执行引擎,则该字段会出现。
explain.queryPlanner.winningPlan.isCached
一个布尔值,表示 winningPlan 是否在计划缓存中。
此字段在获胜计划与被拒绝的计划之间最多有一个计划时为
true
。如果没有缓存的计划,则获胜计划与被拒绝的计划为false
。
explain.queryPlanner.winningPlan.queryPlan
该文档详细说明了查询优化器选择的计划。MongoDB以阶段树的形式展示该计划。
当查询使用了基于槽位的执行查询引擎时,此文档会显示。
新增在版本中5.1.
explain.queryPlanner.winningPlan.queryPlan.stage
一个字符串,表示阶段的名称。
每个阶段都包含该阶段特定的信息。例如,
IXSCAN
阶段包括索引边界以及其他特定于索引扫描的数据。
explain.queryPlanner.winningPlan.queryPlan.planNodeId
用于标识执行计划中每个阶段的唯一整数字段。该字段包含在所有阶段的
explain
结果中。新增在版本中5.1.
explain.queryPlanner.winningPlan.slotBasedPlan.stages
包含有关每个阶段的信息的字符串,包括执行顺序、操作和槽分配。 仅供MongoDB内部使用。
从 MongoDB 8.0 开始,如果查询使用了块处理,则
block_to_row
和ts_bucket_to_cellblock
将出现在stages
输出中。更改在版本中8.0.
explain.queryPlanner.rejectedPlans
查询优化器考虑并拒绝的候选计划数组。如果没有其他候选计划,则数组可以为空。
拒绝的计划与
explain.queryPlanner.winningPlan
具有相同的字段。从 MongoDB 8.0 开始,拒绝的查询计划只包含查询的
find
部分。在之前的版本中,拒绝的计划可以包含类似于$group
的聚合阶段。这些聚合阶段不会被查询规划器用于选择获胜计划,因此rejectedPlans
字段仅包含用于选择获胜计划的查询部分。
executionStats
返回的 explain.executionStats
信息详细说明了获胜计划的执行情况。为了将 executionStats
包含在结果中,您必须在以下任一模式下运行 explain:
allPlansExecution 详尽模式。使用
allPlansExecution
模式以包括在 计划选择 期间捕获的部分执行数据。
这些示例可能结合了MongoDB经典和基于槽位的执行引擎的输出结构。它们并不代表所有情况。您的输出可能会有很大差异。
对于非分片集合,explain
返回以下 executionStats
信息
executionStats: { executionSuccess: <boolean>, nReturned: <int>, executionTimeMillis: <int>, totalKeysExamined: <int>, totalDocsExamined: <int>, executionStages: { stage: <STAGE1> nReturned: <int>, executionTimeMillisEstimate: <int>, opens: <int>, // Starting in MongoDB 5.1 closes: <int>, // Starting in MongoDB 5.1 works: <int>, advanced: <int>, needTime: <int>, needYield: <int>, saveState: <int>, restoreState: <int>, isEOF: <boolean>, ... inputStage: { stage: <STAGE2>, nReturned: <int>, ... numReads: <int>, // Starting in MongoDB 5.1 ... executionTimeMillisEstimate: <int>, ... inputStage: { ... } } }, allPlansExecution: [ { nReturned: <int>, executionTimeMillisEstimate: <int>, totalKeysExamined: <int>, totalDocsExamined:<int>, executionStages: { stage: <STAGEA>, nReturned: <int>, executionTimeMillisEstimate: <int>, ... inputStage: { stage: <STAGEB>, ... inputStage: { ... } } } }, ... ] operationMetrics: { cpuNanos: <int>, cursorSeeks: <int>, docBytesRead: <int>, docBytesWritten: <int>, docUnitsRead: <int>, docUnitsReturned: <int>, docUnitsWritten: <int>, idxEntryBytesRead: <int>, idxEntryBytesWritten: <int>, idxEntryUnitsRead: <int>, idxEntryUnitsWritten: <int>, totalUnitsWritten: <int>, keysSorted: <int>, sorterSpills: <int> } }
对于分片集合,explain
包含对每个访问分片的执行统计信息。
executionStats: { nReturned: <int>, executionTimeMillis: <int>, totalKeysExamined: <int>, totalDocsExamined: <int>, executionStages: { stage: <STAGE1> nReturned: <int>, executionTimeMillis: <int>, opens: <int>, // Starting in MongoDB 5.1 closes: <int>, // Starting in MongoDB 5.1 totalKeysExamined: <int>, totalDocsExamined: <int>, totalChildMillis: <NumberLong>, shards: [ { shardName: <string>, executionSuccess: <boolean>, executionStages: { stage: <STAGE2>, nReturned: <int>, executionTimeMillisEstimate: <int>, ... chunkSkips: <int>, inputStage: { stage: <STAGE3>, ... numReads: <int>, // Starting in MongoDB 5.1 ... inputStage: { ... } } } }, ... ] } allPlansExecution: [ { shardName: <string>, allPlans: [ { nReturned: <int>, executionTimeMillisEstimate: <int>, totalKeysExamined: <int>, totalDocsExamined:<int>, executionStages: { stage: <STAGEA>, nReturned: <int>, executionTimeMillisEstimate: <int>, ... inputStage: { stage: <STAGEB>, ... inputStage: { ... } } } }, ... ] }, { shardName: <string>, allPlans: [ ... ] }, ... ] }
explain.executionStats
包含描述获胜计划已完成查询执行的统计数据。对于写操作,完成的查询执行是指将进行的修改,但不会将修改应用到数据库中。
explain.executionStats.nReturned
获胜查询计划返回的文档数量。
nReturned
对应于 MongoDB 早期版本中cursor.explain()
返回的n
字段。
explain.executionStats.executionTimeMillis
查询计划选择和查询执行所需的总毫秒数。它包括执行计划选择过程中的试验阶段所需的时间,但不包括将数据传回客户端的网络时间。
explain.executionStats.executionTimeMillis
报告的时间不一定能代表实际的查询时间。在稳态操作期间(当查询计划被缓存时),或者在使用cursor.hint()
与cursor.explain()
一起时,MongoDB 会绕过计划选择过程,导致实际时间更快,从而导致explain.executionStats.executionTimeMillis
的值更低。
explain.executionStats.totalKeysExamined
扫描的索引条目数量。
explain.executionStats.totalKeysExamined
与早期 MongoDB 版本中cursor.explain()
返回的nscanned
字段相对应。
explain.executionStats.totalDocsExamined
查询执行过程中检查的文档数量。检查文档的常见查询执行阶段是
COLLSCAN
和FETCH
。注意
explain.executionStats.totalDocsExamined
指的是检查的文档总数,而不是 返回的文档数。例如,某个阶段可以检查一个文档以应用过滤器。如果该文档被过滤掉,则它已被检查,但不会作为查询结果集的一部分返回。如果在查询执行过程中多次检查文档,
explain.executionStats.totalDocsExamined
将计算每次检查。也就是说,explain.executionStats.totalDocsExamined
不是检查的唯一文档总数的计数。
explain.executionStats.executionStages
以阶段树的形式详细说明获胜计划的完成执行;即一个阶段可以有
inputStage
或多个inputStages
。从MongoDB 5.1版本开始,一个阶段可以有以下输入阶段
thenStage
elseStage
innerStage
outerStage
每个阶段都包含特定于该阶段的执行信息。
explain.executionStats.executionStages.works
指定查询执行阶段执行的“工作单元”数量。查询执行将工作划分为小的单元。一个“工作单元”可能包括检查单个索引键、从集合中检索单个文档、对一个文档应用投影或进行一项内部簿记。
如果使用了经典查询执行引擎,则该字段会出现。
explain.executionStats.executionStages.isEOF
指定执行阶段是否到达流末尾
如果为
true
或1
,则执行阶段已到达流末尾。如果为
false
或0
,阶段可能仍然有要返回的结果。例如,考虑一个具有限制的查询,其执行阶段由一个LIMIT
阶段组成,该阶段具有查询的IXSCAN
输入阶段。如果查询返回超过指定的限制,则LIMIT
阶段将报告isEOF: 1
,但它的底层IXSCAN
阶段将报告isEOF: 0
。
explain.executionStats.executionStages.inputStage
每个
inputStage
可以根据inputStage.stage
的值具有不同的字段。下表描述了可能的字段以及它们可以出现在哪些阶段。每个
inputStage
可以将另一个inputStage
作为字段。请参见解释输出结构。字段描述适用阶段docsExamined
指定在查询执行阶段扫描的文档数量。COLLSCAN
、FETCH
keysExamined
对于扫描索引的查询执行阶段,keysExamined
是在索引扫描过程中检查的总数,包括边界内和边界外的键。如果索引扫描由单个连续键范围组成,则只需检查边界内键。如果索引边界由多个键范围组成,则索引扫描执行过程可能会检查边界外的键,以便从一个范围的末尾跳到下一个范围的开始。IXSCAN
numReads
在查询执行阶段扫描的文档或索引键的数量。
新增在版本中5.1.
COLLSCAN
、IXSCAN
seeks
我们需要将索引游标移动到新位置以完成索引扫描的次数。IXSCAN
spilledBytesApprox
该阶段中约有多少内存字节被写入磁盘。
新增在版本中5.3.
GROUP
spilledRecords
该阶段写入磁盘的记录数。
新增在版本中5.3.
GROUP
usedDisk
该阶段是否写入磁盘。
新增在版本中5.3.
GROUP
explain.executionStats.allPlansExecution
包含在计划选择阶段期间捕获的部分执行信息,包括获胜和被拒绝的计划。只有当
explain
以allPlansExecution
详细模式运行时,该字段才存在。
explain.executionStats.operationMetrics
包含资源消耗统计信息,只要它们不为零。只有在
explain
在executionStats
繁琐模式或更高模式运行,并且profileOperationResourceConsumptionMetrics
已启用时,该字段才存在。
serverInfo
对于非分片集合,explain
返回 MongoDB 实例的以下 serverInfo
信息
serverInfo: { host: <string>, port: <int>, version: <string>, gitVersion: <string> }
对于分片集合,explain
返回每个访问的分片的信息,以及一个顶层 serverInfo
对象,用于 mongos
。
queryPlanner: { ... winningPlan: { stage: <STAGE1>, shards: [ { shardName: <string>, connectionString: <string>, serverInfo: { host: <string>, port: <int>, version: <string>, gitVersion: <string> }, ... } ... ] } }, serverInfo: { // serverInfo for mongos host: <string>, port: <int>, version: <string>, gitVersion: <string> } ...
具有 $lookup
管道阶段的查询的执行计划统计信息
新增在版本中5.0.
解释结果可以包括使用 解释结果 的查询执行统计信息,这些查询使用了 $lookup
管道阶段。要包括这些执行统计信息,您必须在以下执行详细模式之一中运行解释操作
以下字段包含在 $lookup
查询的解释结果中
'$lookup': { from: <string>, as: <string>, localField: <string>, foreignField: <string> }, totalDocsExamined: <long>, totalKeysExamined: <long>, collectionScans: <long>, indexesUsed: [ <string_1>, <string_2>, ..., <string_n> ], executionTimeMillisEstimate: <long>
要查看 $lookup
部分中字段的描述,请参阅 $lookup
页面。
其他字段包括
集合扫描
如果查询计划器选择集合扫描,则解释结果包括一个 COLLSCAN
阶段。
如果查询计划器选择索引,则解释结果包括一个 IXSCAN
阶段。该阶段包括索引键模式、遍历方向和索引范围等信息。
从 MongoDB 5.3 开始,如果查询计划器为 聚集索引 选择一个 聚集集合,并且查询包含定义要搜索的索引部分的边界,则解释结果包括一个 CLUSTERED_IXSCAN
阶段。该阶段包括有关聚集索引键和索引范围的信息。
如果查询计划器为 聚集索引 选择一个 聚集集合,并且查询 不 包含边界,则查询执行无边界集合扫描,并且解释结果包括一个 COLLSCAN
阶段。
注意
不允许使用聚集索引的无边界查询 notablescan
参数,因为查询需要全集合扫描。
有关集合扫描的执行统计信息,请参阅 解释 Explain 计划结果。
覆盖查询
当一个索引 覆盖 一个查询时,MongoDB 可以匹配查询条件 并且 只使用索引键返回结果。MongoDB 不需要检查集合中的文档来执行查询的任何部分。
当索引覆盖查询时,解释结果中有一个 IXSCAN
阶段,它 不是 FETCH
阶段的子节点,并且在 executionStats
中,explain.executionStats.totalDocsExamined
的值是 0
。
$or
表达式
如果 MongoDB 使用索引处理 $or
表达式,结果将包括具有详细索引的 OR
阶段和 explain.queryPlanner.winningPlan.inputStages
数组;例如。
{ stage: 'OR', inputStages: [ { stage: 'IXSCAN', ... }, { stage : 'IXSCAN', ... }, ... ] }
在 MongoDB 之前版本中,cursor.explain()
返回包含详细索引的 clauses
数组。
$sort
和 $group
阶段
当在 executionStats 或 allPlansExecution 详尽模式中运行 explain
时,$sort
和 $group
阶段有额外的输出。
排序阶段
如果MongoDB无法使用索引或索引来获取排序顺序,结果将包括一个表示阻塞排序操作的SORT
阶段。阻塞排序不会阻塞集合或数据库上的并发操作。该名称指的是SORT
阶段需要在返回任何输出文档之前读取所有输入文档,从而阻塞该特定查询的数据流。
如果MongoDB需要使用超过100兆字节的系统内存来进行阻塞排序操作,MongoDB将返回一个错误除非查询指定了cursor.allowDiskUse()
。 cursor.allowDiskUse()
允许MongoDB在处理阻塞排序操作时使用磁盘上的临时文件来存储超出100兆字节系统内存限制的数据。如果查询计划中不包含显式的SORT
阶段,则MongoDB可以使用索引来获取排序顺序。
查询形状哈希
从 MongoDB 8.0 开始,explain
输出以下字段
explain.queryShapeHash
表示查询形状的哈希值的十六进制字符串。更多信息,请参阅 查询形状。
新增在版本中8.0.