MongoDB提供了db.collection.explain()
方法, cursor.explain()
方法, 和explain
命令去返回查询计划信息和查询计划的执行统计信息。
explain
结果中呈现的查询计划可以看做一个阶段树。每个阶段将其结果(即文档或索引键)传递给父节点。
子节点访问文档或索引,内部节点操作由子节点产生的文档或索引键。根节点是从MongoDB获取结果集的最后阶段。
阶段是对操作的描述;例如:
COLLSCAN
全表扫描IXSCAN
索引扫描FETCH
根据索引去检索文档SHARD_MERGE
合并分片结果
输出
下面的部分展示了explain
操作返回的一些关键字段的列表。
注
- 以下字段列表并不详尽,但是它展现了explain
命令某些关键字段最精彩的改变。
- 输出格式是受版本之间的变化影响。
queryPlanner
queryPlanner字段中展示了查询优化器选择查询计划的详细信息。
{
"queryPlanner" : {
"plannerVersion" : <int>,
"namespace" : <string>,
"indexFilterSet" : <boolean>,
"parsedQuery" : {
...
},
"winningPlan" : {
"stage" : <STAGE1>,
...
"inputStage" : {
"stage" : <STAGE2>,
...
"inputStage" : {
...
}
}
},
"rejectedPlans" : [
<candidate plan 1>,
...
]
}
}
explain.queryPlanner
包含查询优化器选择的查询计划的信息。
explain.queryPlanner.namespace
该查询计划所查询的表(格式如: <database>.<collection>
)。
explain.queryPlanner.indexFilterSet
对于该查询模型是否有索引过滤。
explain.queryPlanner.winningPlan
被查询优化器选择的查询计划详情. MongoDB以阶段树形式展示该详情; 一个阶段可以有一个inputStage
,或多个子阶段和inputStages
。
explain.queryPlanner.winningPlan.stage
中标计划的阶段名标识。
每个阶段都包括特定阶段的信息。例如,一个IXSCAN
阶段将包括索引界限以及其他特定的索引扫描数据。如果一个阶段有一个子或多个子阶段,那么将有一个inputstage
或inputstages
。
explain.queryPlanner.winningPlan.inputStage
描述子阶段的文档。为父阶段提供文档和索引。当父阶段只有一个子阶段时该字段存在。
explain.queryPlanner.winningPlan.inputStages
描述所有子阶段的文档数组。 为父阶段提供文档集和索引集. 当父阶段有多个子阶段时该字段存在。例如:$or或 index intersection 阶段消费多个源输入。
explain.queryPlanner.rejectedPlans
其他执行计划(非最优而被查询优化器reject的)的详情数组。如果没有其他候选计划,数组为空。
executionStats
中标计划执行统计详情。
为了让executionStats
出现在结果中,运行explain
时必须使用executionStats或allPlansExecution冗长模式。
例如: db.records.find( { a: 1 } ).explain("executionStats")
为了包括plan selection期间捕获到的部分执行数据,你必须运行在allplansexecution
模式。
对于未分片的集合,explain
将返回下面的信息:
{
"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>,
"isEOF" : <boolean>,
...
"inputStage" : {
"stage" : <STAGE2>,
...
"nReturned" : 0,
"executionTimeMillisEstimate" : <int>,
...
"inputStage" : {
...
}
}
},
"allPlansExecution" : [
{ <partial executionStats1> },
{ <partial executionStats2> },
...
]
}
}
explain.executionStats
包含描述中标计划查询执行完成的统计信息。对于写操作,完成的查询执行是指将执行的修改,但是不会应用这个修改到数据库。
explain.executionStats.nReturned
查询条件匹配到的文档个数,和早期版本中的n
是一样的。
explain.executionStats.executionTimeMillis
查询计划选择和查询执行总体花费的时间(单位:毫秒),和早期版本中的millis
是一样的。
explain.executionStats.totalKeysExamined
索引整体扫描的文档个数,和早期版本中的nscanned
是一样的。
explain.executionStats.totalDocsExamined
整体扫描的文档个数,和早期版本中的nscannedObjects
是一样的。
explain.executionStats.executionStages
中标计划执行完成各个阶段的统计信息。一个阶段可以有一个inputStage
或多个inputStages
。每个阶段包括特定阶段的执行信息。
explain.executionStats.executionStages.works
指定由查询执行阶段执行的“工作单元”的数量。查询执行将其工作划分为小工作单元。一个“工作单元”可能包括检查一个索引键,从集合中提取单个文档,将一个投影应用到一个单一的文档,或者记录一个内部档案。
explain.executionStats.executionStages.advanced
优先返回给父阶段的中间结果集中文档个数。
explain.executionStats.executionStages.needTime
未优先返回给父阶段的中间结果集的工作周期次数。
例如,索引扫描阶段可能会花费一个工作周期在这个索引中寻求一个新的位置而不是直接返回该索引键;本工作周期将计入explain.executionstats.executionstages.needtime
而不是explain.executionstats.executionstages.advanced
。
explain.executionStats.executionStages.needYield
存储层请求查询系统让出锁的次数。
explain.executionStats.executionStages.isEOF
查询执行是否已经到了数据流的末尾:
如果是true
或1
, 则到达末尾.
如果是false
或0
, 则该阶段仍有结果返回. 例如, limit
查询,IXSCAN
阶段为LIMIT
执行阶段提供输入,当查询返回的文档个数超出限制时,LIMIT
将会是1
, 而IXSCAN
阶段却会是0
;
explain.executionStats.allPlansExecution
在方案选择阶段期间捕获到的特定(中标计划和拒绝计划)的执行信息。该字段只在allPlansExecution
冗长模式下运行explain
才显示。
对于分片集合,explain
也包含每个分片访问相关的执行统计,如果想查看详情,请移步Sharded Collection;
参考链接: Explain Results & Mongodb使用explain优化查询(1)–explain输出参数解析