Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs 菜单
Docs 主页
/
MongoDB Manual
/

解释结果

为了返回查询计划和查询计划执行统计信息,MongoDB 提供:

explain 结果将查询计划显示为阶段树。

"winningPlan" : {
"stage" : <STAGE1>,
...
"inputStage" : {
"stage" : <STAGE2>,
...
"inputStage" : {
"stage" : <STAGE3>,
...
}
}
},

每个阶段都会传递其结果(即 文档或索引键)复制到父节点。 叶节点访问权限集合或索引。 内部节点操作由子节点产生的文档或索引键。 节点是MongoDB派生结果设立的最后阶段。

阶段是对操作的描述;例如

  • COLLSCAN 用于集合扫描

  • IXSCAN 用于扫描索引键

  • FETCH 用于检索文档

  • SHARD_MERGE 用来合并来自分片的结果

  • SHARDING_FILTER 用于从分片中筛掉孤儿文档

以下部分列出了explain操作返回的一些关键字段。

注意

  • 该字段列表并非详尽无遗,而是旨在突出显示与早期版本的explain相比的一些关键字字段更改。

  • 输出格式可能因版本而异。

queryPlanner 信息详细说明了查询优化器选择的计划。

对于未分片的集合,explain 将返回以下 queryPlanner 信息:

"queryPlanner" : {
"plannerVersion" : <int>,
"namespace" : <string>,
"indexFilterSet" : <boolean>,
"parsedQuery" : {
...
},
"queryHash" : <hexadecimal string>,
"planCacheKey" : <hexadecimal string>,
"optimizedPipeline" : <boolean>, // Starting in MongoDB 4.2, only appears if true
"winningPlan" : {
"stage" : <STAGE1>,
...
"inputStage" : {
"stage" : <STAGE2>,
...
"inputStage" : {
...
}
}
},
"rejectedPlans" : [
<candidate plan 1>,
...
]
}

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

"queryPlanner" : {
"mongosPlannerVersion" : <int>,
"winningPlan" : {
"stage" : <STAGE1>,
"shards" : [
{
"shardName" : <string>,
"connectionString" : <string>,
"serverInfo" : {
"host" : <string>,
"port" : <int>,
"version" : <string>,
"gitVersion" : <string>
},
"plannerVersion" : <int>,
"namespace" : <string>,
"parsedQuery" : <document>,
"queryHash" : <hexadecimal string>,
"planCacheKey" : <hexadecimal string>,
"optimizedPipeline" : <boolean>, // Starting in MongoDB 4.2, only appears if true
"winningPlan" : {
"stage" : <STAGE2>,
"inputStage" : {
"stage" : <STAGE3>
...,
}
},
rejectedPlans: [
<candidate plan1>,
]
}
]
}
}
explain.queryPlanner

包含查询优化器所选查询计划的相关信息。

explain.queryPlanner.namespace

一个字符串,使用数据库的名称和查询访问的集合指定该命名空间。该命名空间的格式为 <database>.<collection>

explain.queryPlanner.indexFilterSet

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

explain.queryPlanner.queryHash

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

注意

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

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

4.2 版本中的新增功能

explain.queryPlanner.planCacheKey

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

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

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

4.2 版本中的新增功能

explain.queryPlanner.optimizedPipeline

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

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

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

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

4.2 版本中的新增功能

explain.queryPlanner.winningPlan

详细说明查询优化器所选计划的文档。 MongoDB将计划表示为阶段树;即一个阶段可以有一个inputStage ,或者,如果该阶段有多个子阶段,则可以有一个inputStages

explain.queryPlanner.winningPlan.stage

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

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

explain.queryPlanner.winningPlan.inputStage

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

explain.queryPlanner.winningPlan.inputStages

描述子阶段的文档数组。 子阶段为父阶段提供文档或索引键。 如果父阶段有多个子节点,则该字段存在。 例如, $or 表达式索引交集的阶段使用来自多个源的输入。

explain.queryPlanner.rejectedPlans

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

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

对于未分片的集合,explain 将返回以下 executionStats 信息:

"executionStats" : {
"executionSuccess" : <boolean>,
"nReturned" : <int>,
"executionTimeMillis" : <int>,
"totalKeysExamined" : <int>,
"totalDocsExamined" : <int>,
"executionStages" : {
"stage" : <STAGE1>
"nReturned" : <int>,
"executionTimeMillisEstimate" : <int>,
"works" : <int>,
"advanced" : <int>,
"needTime" : <int>,
"needYield" : <int>,
"saveState" : <int>,
"restoreState" : <int>,
"isEOF" : <boolean>,
...
"inputStage" : {
"stage" : <STAGE2>,
"nReturned" : <int>,
"executionTimeMillisEstimate" : <int>,
...
"inputStage" : {
...
}
}
},
"allPlansExecution" : [
{
"nReturned" : <int>,
"executionTimeMillisEstimate" : <int>,
"totalKeysExamined" : <int>,
"totalDocsExamined" :<int>,
"executionStages" : {
"stage" : <STAGEA>,
"nReturned" : <int>,
"executionTimeMillisEstimate" : <int>,
...
"inputStage" : {
"stage" : <STAGEB>,
...
"inputStage" : {
...
}
}
}
},
...
]
}

对于分片集合,explain 包括每个访问的分片的执行统计信息。

"executionStats" : {
"nReturned" : <int>,
"executionTimeMillis" : <int>,
"totalKeysExamined" : <int>,
"totalDocsExamined" : <int>,
"executionStages" : {
"stage" : <STAGE1>
"nReturned" : <int>,
"executionTimeMillis" : <int>,
"totalKeysExamined" : <int>,
"totalDocsExamined" : <int>,
"totalChildMillis" : <NumberLong>,
"shards" : [
{
"shardName" : <string>,
"executionSuccess" : <boolean>,
"executionStages" : {
"stage" : <STAGE2>,
"nReturned" : <int>,
"executionTimeMillisEstimate" : <int>,
...
"chunkSkips" : <int>,
"inputStage" : {
"stage" : <STAGE3>,
...
"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

扫描的索引项数。totalKeysExamined 对应于早期版本的 MongoDB 中的 cursor.explain() 返回的 nscanned 字段。

explain.executionStats.totalDocsExamined

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

注意

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

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

explain.executionStats.executionStages

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

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

explain.executionStats.executionStages.executionTimeMillisEstimate

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

explain.executionStats.executionStages.works

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

explain.executionStats.executionStages.advanced

此阶段返回到其父阶段的中间结果的数量。

explain.executionStats.executionStages.needTime

未将中间结果推进到其父阶段的工作周期数(请参阅explain.executionStats.executionStages.advanced )。 例如,索引扫描阶段可能会花费一个工作周期来寻找索引中的新位置,而不是返回索引键;此工作周期将计入explain.executionStats.executionStages.needTime而不是explain.executionStats.executionStages.advanced

explain.executionStats.executionStages.needYield

存储层请求查询阶段暂停处理并让出其锁的次数。

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.keysExamined

对于扫描索引的查询执行阶段(例如 IXSCAN), keysExamined是索引扫描过程中检查的界内和界外键的总数。 如果索引扫描由单个连续范围的键组成,则仅需要检查界内键。 如果索引边界由多个键范围组成,则索引扫描执行过程可能会检查越界键,以便从一个范围的末尾跳到下一个范围的开头。

考虑以下示例,其中存在字段x的索引,并且集合包含100个文档,其x值为1到100 :

db.keys.find( { x : { $in : [ 3, 4, 50, 74, 75, 90 ] } } ).explain( "executionStats" )

查询将扫描键34 。 然后,它将扫描键5 ,检测到其越界,并跳到下一个键50

继续此过程,查询会扫描键3 、 4 、 5 、 50 、 51 、 74 、 75 、 76 、 90和91 。 键5517691是仍在检查中的界外键。 keysExamined的值为10 。

explain.executionStats.executionStages.inputStage.docsExamined

指定在查询执行阶段扫描的文档数量。

针对COLLSCAN阶段以及从集合中检索文档(例如 FETCH )

explain.executionStats.executionStages.inputStage.seeks

3.4版本新增: 仅适用于索引扫描 ( IXSCAN ) 阶段。

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

explain.executionStats.allPlansExecution

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

版本 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

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

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

从 MongoDB 3.0开始, explain结果的格式和字段与以前的版本相比已发生变化。 下面列出了一些主要区别。

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

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

在 MongoDB 的早期版本中, cursor.explain()返回的cursor字段具有以下值:

  • BasicCursor 用于集合扫描,以及

  • BtreeCursor <index name> [<direction>] 用于索引扫描。

有关集合扫描与索引扫描的执行统计信息的更多信息,请参阅分析查询性能。

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

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

在MongoDB的早期版本中, cursor.explain()返回indexOnly字段以指示索引是否覆盖查询。

对于索引相交计划,结果将包括AND_SORTED阶段或AND_HASH阶段,以及详细说明索引的inputStages数组;例如:

{
"stage" : "AND_SORTED",
"inputStages" : [
{
"stage" : "IXSCAN",
...
},
{
"stage" : "IXSCAN",
...
}
]
}

在 MongoDB 的早期版本中,对于索引交集, cursor.explain()返回值为Complex Plancursor字段。

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

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

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

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

阶段
字段
类型
说明

totalDataSizeSortedBytesEstimate

long

$sort 阶段处理的字节估计数。

usedDisk

布尔

$sort 阶段是否已写入磁盘。

totalOutputDataSizeBytes

long

$group 阶段输出的所有文档总大小的估计值(以字节为单位)。

usedDisk

布尔

$group 阶段是否已写入磁盘。

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

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

后退

分析性能

在此页面上