首页 > 数据库 > > MongDB查询性能分析——explain 结果详解
MongoDB 提供 db.collection.explain(), cursort.explain() 及 explain 命令获取查询计划及查询计划执行统计信息。
explain 结果将查询计划以阶段树的形式呈现。 每个阶段将其结果(文档或索引键)传递给父节点。 叶节点访问集合或索引。 中间节点操纵由子节点产生的文档或索引键。 根节点是MongoDB从中派生结果集的最后阶段。
阶段操作描述,例:
queryPlanner 显示的是被查询优化器选择出来的查询计划。
以下未分片集合 explain 操作结果如下:
{
"queryPlanner" : {
"plannerVersion" : <int>,
"namespace" : <string>,
"indexFilterSet" : <boolean>,
"parsedQuery" : {
...
},
"winningPlan" : {
"stage" : <STAGE1>,
...
"inputStage" : {
"stage" : <STAGE2>,
...
"inputStage" : {
...
}
}
},
"rejectedPlans" : [
<candidate plan 1>,
...
]
}
对于分片集合,获胜计划包括分每个访问的分片的计划信息数组。
executionStats 返回的是获胜计划执行相关信息。必须在 executionStats 或 allPlansExecution 详细模式下运行explain才显示executionStats 相关信息。
要捕获选择执行计划期间执行相关信息,必须使用 allPlansExecution 模式运行。
executionStats 模式 explain 实例:
db.products.explain("executionStats").find(
{ quantity: { $gt: 50 }, category: "apparel" }
)
allPlansExecution 模式 explain 实例:
db.products.explain("allPlansExecution").update(
{ quantity: { $lt: 1000}, category: "apparel" },
{ $set: { reorder: true } }
)
以下未分片集合 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" : <int>,
"executionTimeMillisEstimate" : <int>,
"keysExamined" : <int>,
"docsExamined" : <int>,
...
"inputStage" : {
...
}
}
},
"allPlansExecution" : [
{ <partial executionStats1> },
{ <partial executionStats2> },
...
]
}
考虑以下示例,集合包含字段x值为1到100的100个文档,其中索引字段为x:javascript for(var x=1;x<=100;x++){ db.keys.insert({x:x}); } db.keys.ensureIndex({x:1}); db.keys.find( { x : { $in : [ 3, 4, 50, 74, 75, 90 ] } } ).explain( "executionStats" )
该查询将扫描键3和4.然后它将扫描键5,检测它是否超出界限,并跳到下一个键50。
继续该过程,查询扫描键3,4,5,50,51,74,75,76,90和91.键5,51,76和91是仍在检查的越界键。 keysExamined的值为10。
对于未分片的集合,MongoDB实例explain返回以下信息:
"serverInfo" : {
"host" : <string>,
"port" : <int>,
"version" : <string>,
"gitVersion" : <string>
}
对于分片集合,explain返回每个访问的分片的serverInfo。
对于分片集合,explain在shards字段中返回每个访问的分片的核心查询规划器和服务器信息:
{
"queryPlanner" : {
...
"winningPlan" : {
...
"shards" : [
{
"shardName" : <shard>,
<queryPlanner information for shard>,
<serverInfo for shard>
},
...
],
},
},
"executionStats" : {
...
"executionStages" : {
...
"shards" : [
{
"shardName" : <shard>,
<executionStats for shard>
},
...
]
},
"allPlansExecution" : [
{
"shardName" : <string>,
"allPlans" : [ ... ]
},
...
]
}
}
在 3.0 版本中的修改。
explain 结果的格式和字段与以前的版本相比有所变化。 以下列出了一些主要差异。
如果查询计划程序选择了集合扫描,则说明结果包括COLLSCAN阶段。
如果查询计划程序选择索引,则说明结果包括IXSCAN阶段。 该阶段包括诸如索引key的匹配,遍历方向和索引边界之类的信息。
在早期版本的MongoDB中,cursor.explain() 返回了光标字段,其值为:
用于集合扫描的BasicCursor,以及索引扫描的BtreeCursor <索引名称> [<方向>]。
当索引覆盖查询时,MongoDB可以匹配查询条件并仅使用索引键返回结果; 即MongoDB不需要检查集合中的文档以返回结果。
当索引覆盖查询时,解释结果的IXSCAN阶段不是FETCH阶段的后代,而在executionStats中,totalDocsExamined为0。
在早期版本的MongoDB中,cursor.explain() 返回indexOnly字段以指示索引是否覆盖了查询。
对于索引交集计划,结果将包括AND_SORTED阶段或AND_HASH阶段,其中包含详细说明索引的inputStages数组; 例如。:
{
"stage" : "AND_SORTED",
"inputStages" : [
{
"stage" : "IXSCAN",
...
},
{
"stage" : "IXSCAN",
...
}
]
}
在以前版本的MongoDB中,cursor.explain() 返回了游标字段,其中包含索引交叉点的复杂计划。
如果MongoDB使用$or 表达式的索引,则结果将包含OR阶段,其中包含详细说明索引的inputStages数组; 例如。:
{
"stage" : "OR",
"inputStages" : [
{
"stage" : "IXSCAN",
...
},
{
"stage" : "IXSCAN",
...
},
...
]
}
在早期版本的MongoDB中,cursor.explain() 返回了详细索引的子句数组。
如果MongoDB可以使用索引扫描来获取请求的排序顺序,则结果将不包括SORT阶段。 否则,如果MongoDB无法使用索引进行排序,则解释结果将包括SORT阶段。
在MongoDB 3.0之前,cursor.explain() 返回scanAndOrder字段以指定MongoDB是否可以使用索引顺序返回排序结果。
Fetch+IDHACK
Fetch+ixscan
Limit+(Fetch+ixscan)
PROJECTION+ixscan
SHARDING_FILTER+ixscan
COUNT_SCAN
...
COLLSCAN(全表扫描),
SORT(使用sort但是无index),
不合理的SKIP,
SUBPLA(未用到index的$or),
COUNTSCAN
作者:学习园
来自个人博客: http://www.xuexiyuan.cn/article/detail/179.html
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31537575/viewspace-3124792/ ,如需转载,请注明出处,否则将追究法律责任。