Docs 菜单
Docs 主页
/
MongoDB Manual
/ / / /

解释结果

在此页面上

  • 解释输出结构
  • 解释 MongoDB 5.1 和更高版本的输出
  • queryPlanner
  • executionStats
  • serverInfo
  • 使用 $lookup 管道阶段的查询的执行计划统计信息
  • 集合扫描(collection scan)
  • 覆盖查询
  • $or 表达式(expression)
  • $sort$group 阶段
  • 排序阶段

要返回有关查询计划的信息以及查询计划的执行统计信息,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 及更高版本的 explain 输出。要查看旧版本 MongoDB 的解释输出,请参阅该版本的文档。

explain.explainVersion

整型字段。

explainVersion 是该计划的输出格式版本,例如 "1""2"

5.1 版本中的新功能

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>,
]
}

对于分片集合, explainshards字段中包含每个访问的分片的核心查询规划器和服务器信息:

{
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.indexFilterSet

一个布尔值,它指定了 MongoDB 是否对查询结构应用了索引筛选器

explain.queryPlanner.queryHash

一个十六进制字符串,表示查询结构的哈希值,且仅取决于查询结构。queryHash 有助于识别具有相同查询结构的慢查询(包括写入操作的查询筛选器)。

注意

与任何哈希函数一样,两个不同的查询结构可能会产生相同的哈希值。但是,不同查询结构之间不太可能发生哈希冲突。

有关 queryHashplanCacheKey 的更多信息,请参阅 queryHashplanCacheKey

explain.queryPlanner.planCacheKey

与此查询关联的计划缓存条目的键的哈希值。

explain.queryPlanner.queryHash 不同,explain.queryPlanner.planCacheKey 是查询结构和该结构当前可用索引的函数。换言之,如果添加/删除可以支持该查询结构的索引,则 planCacheKey 值可能会更改,而 queryHash 值不会更改。

有关 queryHashplanCacheKey 的更多信息,请参阅 queryHashplanCacheKey

explain.queryPlanner.optimizedPipeline

一个布尔值,表明整个聚合管道操作已被优化掉,改用查询计划执行阶段树来实现。

例如,以下聚合操作可以通过查询计划执行树来完成,而不使用聚合管道。

db.example.aggregate([ { $match: { someFlag: true } } ] )

仅当值为 true 时,该字段才存在,并且仅适用于解释聚合管道操作。为 true 时,由于管道已被优化掉,所以输出中不会出现聚合阶段信息。

explain.queryPlanner.winningPlan

详细说明查询优化器所选计划的文档。

explain.queryPlanner.winningPlan.stage

一个表示阶段名称的字符串。

每个阶段都包含针对该阶段的信息。例如,IXSCAN 阶段包括索引边界和索引扫描的其他特定数据。如果一个阶段有一个或多个子阶段,则该阶段将有一个 inputStageinputStages

如果该操作使用经典查询执行引擎,则会显示此字段。

explain.queryPlanner.winningPlan.inputStage

一份描述该子阶段的文档,该子阶段为其父阶段提供文档或索引键。如果父阶段只有一个子阶段,则该字段存在。

explain.queryPlanner.winningPlan.inputStages

描述子阶段的一系列文档。子阶段为父阶段提供文档或索引键。如果父阶段有多个子节点,则该字段存在。例如,$or 表达式的阶段可能会消耗多个来源的输入。

如果该操作使用经典查询执行引擎,则会显示此字段。

explain.queryPlanner.winningPlan.isCached

一个布尔值,表示winingPlan 是否在计划缓存中。

对于获胜计划和被拒绝计划之间最多一个计划,此字段为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.queryPlan.inputStage

请参阅 explain.queryPlanner.winningPlan.inputStage

explain.queryPlanner.winningPlan.slotBasedPlan

一份文档,包含有关基于槽位的查询执行计划树和阶段的信息。供 MongoDB 内部使用。

5.1 版本中的新功能

explain.queryPlanner.rejectedPlans

查询优化器考虑和拒绝的候选计划数组。如果没有其他候选计划,则数组可能为空。

被拒绝的计划具有与explain.queryPlanner.winningPlan相同的字段。

返回的 explain.executionStats 信息详细说明了获胜计划的执行情况。为了在结果中包含 executionStats,您必须在如下位置运行解释:

这些示例可能结合了 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

查询执行过程中检查的文档数量。检查文档的常见查询执行阶段是 COLLSCANFETCH

注意

explain.executionStats.totalDocsExamined 是指已检查的文档总数,而非返回的文档数量。例如,阶段可以按照顺序检查文档以应用过滤器。如果文档被过滤掉,则说明它已被检查过,但不会纳入查询结果集返回。

如果在查询执行过程中多次检查了一个文档,explain.executionStats.totalDocsExamined 会对每次检查进行计数。也就是说,explain.executionStats.totalDocsExamined 不是所检查的唯一文档的总数。

explain.executionStats.executionStages

以阶段树的形式详细说明获胜计划的执行情况;即一个阶段可以有一个 inputStage 或多个 inputStages

从 MongoDB 5.1 开始,一个阶段可以具有以下输入阶段:

  • thenStage

  • elseStage

  • innerStage

  • outerStage

每个阶段都包含针对该阶段的执行信息。

explain.executionStats.executionStages.executionTimeMillisEstimate

查询执行的估计时间(以毫秒为单位)。

explain.executionStats.executionStages.opens

从 MongoDB 5.1 开始,查询执行期间打开阶段的次数。

explain.executionStats.executionStages.closes

从 MongoDB 5.1 开始,查询执行期间阶段关闭的次数。

explain.executionStats.executionStages.works

指定查询执行阶段执行的“工作单元”数量。查询执行将其工作划分为多个小单元。“工作单元”可能包括检查单个索引键、从集合中获取单个文档、将投影应用于单个文档或进行内部簿记。

如果该操作使用经典查询执行引擎,则会显示此字段。

explain.executionStats.executionStages.saveState

查询阶段暂停处理并保存其当前执行状态的次数,例如在准备放弃其锁时。

explain.executionStats.executionStages.restoreState

查询阶段恢复了已保存的执行状态的次数,例如在恢复此前生成的锁之后。

explain.executionStats.executionStages.isEOF

指定执行阶段是否已到达流结束:

  • 如果为 true1,则执行阶段已到达流结束。

  • 如果为 false0,则该阶段可能仍有结果要返回。考虑一个具有限制的查询,其执行阶段由 LIMIT 个阶段组成,输入阶段为 IXSCAN。如果查询返回的结果超过指定的限制,则 LIMIT 阶段将报告 isEOF: 1,但其底层的 IXSCAN 阶段将报告 isEOF: 0

explain.executionStats.executionStages.inputStage

每个 inputStage 可以有不同的字段,具体取决于 inputStage.stage 的值。下表描述了可能的字段以及它们可以出现在哪些阶段。

每个 inputStage 可以具有另一个 inputStage 作为字段。请参阅解释输出结构

字段
说明
适用阶段
docsExamined
指定在查询执行阶段扫描的文档数量。
COLLSCANFETCH
keysExamined
对于扫描索引的查询执行阶段,keysExamined 是在索引扫描过程中检查的界内和界外键的总数。如果索引扫描由单个连续范围的键组成,则仅需要检查界内键。如果索引边界由多个键范围组成,则索引扫描执行过程可能会检查界外键,以便从一个范围的末尾跳到下一个范围的开头。
IXSCAN
numReads

在查询执行阶段扫描的文档或检查的索引键的数量。

5.1 版本中的新功能

COLLSCANIXSCAN
seeks
为了完成索引扫描而必须让索引游标搜索新位置的次数。
IXSCAN
spilledBytesApprox

在该阶段中溢出到磁盘的内存字节大约数。

5.3 版本中的新增功能

GROUP
spilledRecords

在该阶段中溢出到磁盘的生成记录数。

5.3 版本中的新增功能

GROUP
usedDisk

该阶段是否已写入磁盘。

5.3 版本中的新增功能

GROUP
explain.executionStats.allPlansExecution

包含在计划选择阶段为中标和被拒计划捕获的部分执行信息。该字段仅在 explainallPlansExecution 详细模式运行时出现。

explain.executionStats.operationMetrics

包含资源使用情况统计数据(只要该数据不为零)。仅当 explainexecutionStats 详细模式或更高级别的模式下运行并且 profileOperationResourceConsumptionMetrics 处于启用状态时,此字段才会出现。

对于未分片集合, 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>
}
...

版本 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 页面。

其他字段为:

explain.totalDocsExamined

查询执行过程中检查的文档数量。

explain.totalKeysExamined

检查的索引键的数量。

explain.collectionScans

在查询执行期间发生集合扫描的次数。在集合扫描期间,集合中的每个文档都会与查询谓词进行比较。如果不存在涵盖此查询的相应索引,则会进行集合扫描。

explain.indexesUsed

包含查询所用索引名称的字符串的数组。

explain.executionTimeMillisEstimate

查询执行的估计时间(以毫秒为单位)。

如果查询规划器选择集合扫描,解释结果将包含 COLLSCAN 阶段。

如果查询规划器选择索引,解释结果将包含 IXSCAN 阶段。该阶段包括索引键模式、遍历方向和索引边界等信息。

从 MongoDB 5.3 开始,如果查询规划器为集群化集合选择了集群化索引,且查询包含定义要搜索的索引部分的边界,则解释结果会包含一个 CLUSTERED_IXSCAN 阶段。该阶段包含有关集群化索引键和索引边界的信息。

如果查询规划器为集群化集合选择集群化索引,且查询包含边界,则查询将执行无边界集合扫描,解释结果包括 COLLSCAN 阶段。

注意

notablescan 参数不允许使用集群索引的无界查询,因为这些查询需要完整的集合扫描。

有关集合扫描的执行统计数据的更多信息,请参阅解释“解释计划结果”。

当索引覆盖查询时,MongoDB 可以仅使用索引键匹配查询条件返回结果。 MongoDB 无需检查集合中的文档即可执行查询的任何部分。

当索引覆盖查询时,解释结果中有一个 IXSCAN 阶段不是 FETCH 阶段的子代,在 executionStats 中,explain.executionStats.totalDocsExamined0

如果 MongoDB 为 $or 表达式使用索引,那么结果将包括 OR 阶段和一个详细说明索引的 explain.queryPlanner.winningPlan.inputStages 数组;例如:

{
stage: 'OR',
inputStages: [
{
stage: 'IXSCAN',
...
},
{
stage : 'IXSCAN',
...
},
...
]
}

在早期版本的 MongoDB 中,cursor.explain() 返回详细说明索引的 clauses 数组。

explain ExecutionStatsAllplansEx ecution 详细模式下运行时,$sort$group 阶段会有额外的输出。

阶段
字段
类型
说明
totalDataSizeSortedBytesEstimate
$sort 阶段处理的字节估计数。
usedDisk
布尔
$sort 阶段是否已写入磁盘。
totalOutputDataSizeBytes
$group 阶段输出的所有文档总大小的估计值(以字节为单位)。
usedDisk
布尔
$group 阶段是否已写入磁盘。
spillFileSizeBytes
$group 阶段写入磁盘的溢出文件的大小。由于压缩,spillFileSizeBytes 的值应小于或等于 numBytesSpilledEstimate
numBytesSpilledEstimate
压缩前在 $group 阶段写入磁盘的字节估计数。

如果 MongoDB 无法使用一个或多个索引来获取排序顺序,则结果将包含指示阻塞排序操作的 SORT 阶段。阻塞排序不会阻塞对集合或数据库的并发操作。阻塞是指要求 SORT 阶段在返回任何输出文档之前读取所有输入文档,从而阻止该特定查询的数据流。

如果 MongoDB 需要使用超过 100 MB 的系统内存进行阻塞排序操作,则 MongoDB 将返回错误,除非查询指定了 cursor.allowDiskUse()cursor.allowDiskUse() 允许 MongoDB 在处理阻塞排序操作时使用磁盘上的临时文件来存储超过 100 MB 系统内存限制的数据。如果解释计划不包含显式 SORT 阶段,则 MongoDB 可以使用索引来获取排序顺序。

后退

分析性能

来年

解释结果