解释结果
在此页面上
为了返回有关查询计划 和查询计划执行统计信息,MongoDB 提供了以下方法:
要了解重要的解释结果字段以及如何加以解释,请参阅解释“解释计划结果”。
重要
explain
忽略计划缓存。相反,系统会生成一组候选计划,并在不咨询计划缓存的情况下选择获胜者。此外,explain
会阻止 MongoDB 查询规划器缓存获胜计划。
注意
此页面仅显示最重要的输出字段,未记录供内部使用的字段。输出中列出的字段可能会发生变化。
解释输出结构
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
用于从分片中筛掉孤儿文档BATCHED_DELETE
用于在内部批处理的多个文档删除(从 MongoDB 6.1 开始)
解释 MongoDB 5.1 和更高版本的输出
本部分显示 MongoDB 5.1 及更高版本的 explain
输出。要查看旧版本 MongoDB 的解释输出,请参阅该版本的文档。
queryPlanner
explain.queryPlanner
信息详细说明了查询优化器选择的计划。
这些示例可能结合了 MongoDB 的经典执行引擎和基于槽位的执行引擎的输出结构。它们并不具有代表性。您的输出可能与之有巨大差异。
对于未分片的集合,explain
将返回以下 queryPlanner
信息:
queryPlanner: { namespace: <string>, indexFilterSet: <boolean>, parsedQuery: { ... }, queryHash: <hexadecimal string>, planCacheKey: <hexadecimal string>, maxIndexedOrSolutionsReached: <boolean>, maxIndexedAndSolutionsReached: <boolean>, maxScansToExplodeReached: <boolean>, winningPlan: { stage: <STAGE1>, inputStage: { stage: <string>, ... } }, rejectedPlans: [ <candidate plan1>, ] }
对于分片集合,explain
包括核心查询规划器和 shards
字段中每个被访问分片的服务器信息:
{ queryPlanner: { mongosPlannerVersion: <int> winningPlan: { stage: <STAGE1>, shards: [ { shardName: <string>, connectionString: <string>, serverInfo: { ... }, namespace: <string>, indexFilterSet: <boolean>, parsedQuery: { ... }, queryHash: <hexadecimal string>, planCacheKey: <hexadecimal string>, maxIndexedOrSolutionsReached: <boolean>, maxIndexedAndSolutionsReached: <boolean>, maxScansToExplodeReached: <boolean>, winningPlan: { stage: <STAGE1>, inputStage: { stage: <string>, ... } }, rejectedPlans: [ <candidate plan1>, ] } ] } } }
explain.queryPlanner
包含查询优化器所选查询计划的相关信息。
explain.queryPlanner.namespace
一个字符串,使用数据库的名称和查询访问的集合指定该命名空间。该命名空间的格式为
<database>.<collection>
。
explain.queryPlanner.queryHash
一个十六进制字符串,表示查询结构的哈希值,且仅取决于查询结构。
queryHash
有助于识别具有相同查询结构的慢查询(包括写入操作的查询筛选器)。注意
与任何哈希函数一样,两个不同的查询结构可能会产生相同的哈希值。但是,不同查询结构之间不太可能发生哈希冲突。
有关
queryHash
和planCacheKey
的更多信息,请参阅queryHash
和planCacheKey
。
explain.queryPlanner.planCacheKey
与此查询关联的计划缓存条目的键的哈希值。
与
explain.queryPlanner.queryHash
不同,explain.queryPlanner.planCacheKey
是查询结构和该结构当前可用索引的函数。换言之,如果添加/删除可以支持该查询结构的索引,则planCacheKey
值可能会更改,而queryHash
值不会更改。有关
queryHash
和planCacheKey
的更多信息,请参阅queryHash
和planCacheKey
。
explain.queryPlanner.optimizedPipeline
一个布尔值,表明整个聚合管道操作已被优化掉,改用查询计划执行阶段树来实现。
例如,以下聚合操作可以通过查询计划执行树来完成,而不使用聚合管道。
db.example.aggregate([ { $match: { someFlag: true } } ] ) 仅当值为
true
时,该字段才存在,并且仅适用于解释聚合管道操作。为true
时,由于管道已被优化掉,所以输出中不会出现聚合阶段信息。
explain.queryPlanner.winningPlan
详细说明查询优化器所选计划的文档。
explain.queryPlanner.winningPlan.stage
一个表示阶段名称的字符串。
每个阶段都包含针对该阶段的信息。例如,
IXSCAN
阶段包括索引边界和索引扫描的其他特定数据。如果一个阶段有一个或多个子阶段,则该阶段将有一个inputStage
或inputStages
。如果该操作使用经典查询执行引擎,则会显示此字段。
explain.queryPlanner.winningPlan.inputStages
描述子阶段的一系列文档。子阶段为父阶段提供文档或索引键。如果父阶段有多个子节点,则该字段存在。例如,$or 表达式的阶段可能会消耗多个来源的输入。
如果该操作使用经典查询执行引擎,则会显示此字段。
explain.queryPlanner.winningPlan.queryPlan
一份详细说明查询优化器所选计划的文档。MongoDB 将计划表示为阶段树。
如果查询使用基于槽位的执行查询引擎,则此文档出现。
5.1 版本中的新功能。
explain.queryPlanner.winningPlan.queryPlan.stage
一个表示阶段名称的字符串。
每个阶段都包含针对该阶段的信息。例如,
IXSCAN
阶段包括索引边界和索引扫描的其他特定数据。
explain.queryPlanner.winningPlan.queryPlan.planNodeId
标识执行计划中每个阶段的唯一整型字段。字段包含在整个
explain
结果的所有阶段中。5.1 版本中的新功能。
executionStats
返回的 explain.executionStats
信息详细说明了获胜计划的执行情况。为了在结果中包含 executionStats
,您必须在如下位置运行解释:
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
的顶级 serverInfo
对象。
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
页面。
其他字段为:
集合扫描(collection scan)
如果查询规划器选择集合扫描,解释结果将包含 COLLSCAN
阶段。
如果查询规划器选择索引,解释结果将包含 IXSCAN
阶段。该阶段包括索引键模式、遍历方向和索引边界等信息。
从 MongoDB 5.3 开始,如果查询规划器为集群化集合选择了集群化索引,且查询包含定义要搜索的索引部分的边界,则解释结果会包含一个 CLUSTERED_IXSCAN
阶段。该阶段包含有关集群化索引键和索引边界的信息。
如果查询规划器为集群化集合选择集群化索引,且查询不包含边界,则查询将执行无边界集合扫描,解释结果包括 COLLSCAN
阶段。
注意
notablescan
参数不允许使用集群索引的无界查询,因为这些查询需要完整的集合扫描。
有关集合扫描的执行统计数据的更多信息,请参阅解释“解释计划结果”。
覆盖查询
当索引覆盖查询时, MongoDB可以仅使用索引键匹配查询条件并返回结果。 MongoDB无需检查集合中的文档即可执行查询的任何部分。
当索引覆盖查询时,解释结果中有一个 IXSCAN
阶段不是 FETCH
阶段的子代,在 executionStats
中,explain.executionStats.totalDocsExamined
是 0
。
$or
表达式(expression)
如果 MongoDB 为 $or
表达式使用索引,那么结果将包括 OR
阶段和一个详细说明索引的 explain.queryPlanner.winningPlan.inputStages
数组;例如:
{ stage: 'OR', inputStages: [ { stage: 'IXSCAN', ... }, { stage : 'IXSCAN', ... }, ... ] }
在早期版本的 MongoDB 中,cursor.explain()
返回详细说明索引的 clauses
数组。
$sort
和$group
阶段
当 explain
在 ExecutionStats 或 AllplansEx ecution 详细模式下运行时,$sort
和 $group
阶段会有额外的输出。
排序阶段
如果 MongoDB 无法使用一个或多个索引来获取排序顺序,则结果将包含指示阻塞排序操作的 SORT
阶段。阻塞排序不会阻塞对集合或数据库的并发操作。阻塞是指要求 SORT
阶段在返回任何输出文档之前读取所有输入文档,从而阻止该特定查询的数据流。
如果 MongoDB 需要使用超过 100 MB 的系统内存进行阻塞排序操作,则 MongoDB 将返回错误,除非查询指定了 cursor.allowDiskUse()
。cursor.allowDiskUse()
允许 MongoDB 在处理阻塞排序操作时使用磁盘上的临时文件来存储超过 100 MB 系统内存限制的数据。如果解释计划不包含显式 SORT
阶段,则 MongoDB 可以使用索引来获取排序顺序。