Docs 菜单
Docs 主页
/
MongoDB Manual
/

解释结果

在此页面上

  • 解释输出
  • queryPlanner
  • executionStats
  • 使用 $lookup 管道阶段的查询的执行计划统计信息
  • serverInfo
  • 3.0格式更改
  • 集合扫描与索引使用
  • 覆盖查询
  • 索引并集
  • $or 表达式(expression)
  • $sort$group 阶段
  • 排序阶段

为了返回查询计划和查询计划执行统计信息,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 可以使用索引来获取排序顺序。

后退

分析性能