mongodb explain使用

114 阅读2分钟

基本用法

db.collection.method(...).explain(<mode>)
db.collection.explain(<mode>).method(...)

explain有三种模式:

  • queryPlanner (默认)
    • 只列出所有可能执行的方案,不会执行实际的语句,显示已经胜出的方案winningPlan
  • executionStats
    • 只执行winningPlan方案,并输出结果
  • allPlansExecution
    • 执行所有的方案,并输出结果
// queryPlanner (默认)
db.collection.find().explain(); || db.collection.explain().find();

// executionStats 模式, 给explain函数传递参数即可
db.collection.find().explain('executionStats');

// allPlansExecution 模式
db.collection.find().explain('allPlansExecution');

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" : { 
        stage: <STAGE3>,
        ...
      } 
    } 
  }, 
  "rejectedPlans" : [ 
    <candidate plan 1>, 
    ... 
  ] 
}

每个阶段都会将其生成的文档或索引键传递给父节点。叶子节点访问集合或索引。内部节点使用由子节点产生的文档或索引键。根节点表示MongoDB最终导出结果集的阶段。

stage阶段类型如下:

  • COLLSCAN:全表扫描
  • IXSCAN:索引扫描
  • FETCH:根据索引去检索指定document
  • SHARD_MERGE:将各个分片返回数据进行merge
  • SORT:表明在内存中进行了排序
  • LIMIT:使用limit限制返回数
  • SKIP:使用skip进行跳过
  • IDHACK:针对_id进行查询
  • SHARDING_FILTER:通过mongos对分片数据进行查询
  • COUNT:利用db.coll.explain().count()之类进行count运算
  • COUNTSCAN: count不使用Index进行count时的stage返回
  • COUNT_SCAN: count使用了Index进行count时的stage返回
  • SUBPLA:未使用到索引的$or查询的stage返回
  • TEXT:使用全文索引进行查询时候的stage返回
  • PROJECTION:限定返回字段时候stage的返回
key描述
queryPlaner.planerVersion执行计划的版本
queryPlaner.namespace命名空间,包含数据库名称和集合名称(database.collection)
queryPlaner.indexFilterSet是否使用了索引
queryPlaner.parsedQuery
queryPlaner.queryHash查询的一个哈希值,帮助识别具有相同查询的慢查询
queryPlaner.planCacheKey与查询关联的计划缓存键的哈希
queryPlaner.winningPlan选择的执行计划,将以树的形式展现;每一个阶段可以有一个 inputStage,如果阶段有多个子阶段,则会返回多个
queryPlaner.winningPlan.stage表示当前阶段的查询方式
queryPlaner.winningPlan.inputStage子阶段的执行情况,子阶段向父阶段提供文档或索引键
queryPlaner.rejectedPlans拒绝的执行计划

示例

  • 表结构与sql
collection名;resource
索引:idx_resource_type
db.resource.find({resource_type: {$in : ["space"]}}).skip(3000).limit(100).explain('');
  • 运行结果
{
  "queryPlanner": {
    "mongosPlannerVersion": 1,
    "winningPlan": {
      "stage": "SINGLE_SHARD",
      "shards": [
        {
          "shardName": "cluster2770-shard-0",
          "connectionString": "xxxx",
          "serverInfo": {
            "host": "xxxxxboe-1",
            "port": 27017,
            "version": "4.0.3.1-49-12-g03e212d",
            "gitVersion": "xxxxx"
          },
          "plannerVersion": 1,
          "namespace": "keel.resource",
          "indexFilterSet": false,
          "parsedQuery": {
            "resource_type": {
              "$eq": "space"
            }
          },
          "winningPlan": {
            "stage": "LIMIT",
            "limitAmount": 100,
            "inputStage": {
              "stage": "FETCH",
              "inputStage": {
                "stage": "SKIP",
                "skipAmount": 3000,
                "inputStage": {
                  "stage": "IXSCAN",
                  "keyPattern": {
                    "resource_type": 1
                  },
                  "indexName": "idx_resource_type",
                  "isMultiKey": false,
                  "multiKeyPaths": {
                    "resource_type": []
                  },
                  "isUnique": false,
                  "isSparse": false,
                  "isPartial": false,
                  "indexVersion": 2,
                  "direction": "forward",
                  "indexBounds": {
                    "resource_type": [
                      "[\"space\", \"space\"]"
                    ]
                  }
                }
              }
            }
          },
          "rejectedPlans": []
        }
      ]
    }
  }
}

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: {
            ...
         }
      }
   }
}
key描述
executionStats.nReturned符合条件的文档数
executionStats.executionTimeMillis解释和查询执行的总时间,单位:毫秒
executionStats.totalKeysExamined扫描索引键数目
executionStats.totalDocsExamined扫描的文档数目。不代表返回的文档数,而且并不是只扫描一次,可能在不同的步骤扫瞄多次
executionStats.executionStages执行情况
executionStats.executionStages.executionTimeMillisEstimate查询的一个预估时间,单位:毫秒
executionStats.executionStages.inputStage子阶段查询

示例

db.resource.find({resource_type: {$in : ["space"]}}).
skip(3000).limit(100).explain('executionStats');
"executionStats": {
    "nReturned": 100,
    "executionTimeMillis": 11,
    "totalKeysExamined": 3100,
    "totalDocsExamined": 100,
    "executionStages": {
        "stage": "SINGLE_SHARD",
        "nReturned": 100,
        "executionTimeMillis": 11,
        "totalKeysExamined": 3100,
        "totalDocsExamined": 100,
        "totalChildMillis": "3",
        "shards": [
            {
                "shardName": "cluster2770-shard-0",
                "executionSuccess": true,
                "executionStages": {
                    "stage": "LIMIT",
                    "nReturned": 100,
                    "executionTimeMillisEstimate": 0,
                    "works": 3101,
                    "advanced": 100,
                    "needTime": 3000,
                    "needYield": 0,
                    "saveState": 24,
                    "restoreState": 24,
                    "isEOF": 1,
                    "invalidates": 0,
                    "limitAmount": 100,
                    "inputStage": {
                        "stage": "FETCH",
                        "nReturned": 100,
                        "executionTimeMillisEstimate": 0,
                        "works": 3100,
                        "advanced": 100,
                        "needTime": 3000,
                        "needYield": 0,
                        "saveState": 24,
                        "restoreState": 24,
                        "isEOF": 0,
                        "invalidates": 0,
                        "docsExamined": 100,
                        "alreadyHasObj": 0,
                        "inputStage": {
                            "stage": "SKIP",
                            "nReturned": 100,
                            "executionTimeMillisEstimate": 0,
                            "works": 3100,
                            "advanced": 100,
                            "needTime": 3000,
                            "needYield": 0,
                            "saveState": 24,
                            "restoreState": 24,
                            "isEOF": 0,
                            "invalidates": 0,
                            "skipAmount": 0,
                            "inputStage": {
                                "stage": "IXSCAN",
                                "nReturned": 3100,
                                "executionTimeMillisEstimate": 0,
                                "works": 3100,
                                "advanced": 3100,
                                "needTime": 0,
                                "needYield": 0,
                                "saveState": 24,
                                "restoreState": 24,
                                "isEOF": 0,
                                "invalidates": 0,
                                "keyPattern": {
                                    "resource_type": 1
                                },
                                "indexName": "idx_resource_type",
                                "isMultiKey": false,
                                "multiKeyPaths": {
                                    "resource_type": []
                                },
                                "isUnique": false,
                                "isSparse": false,
                                "isPartial": false,
                                "indexVersion": 2,
                                "direction": "forward",
                                "indexBounds": {
                                    "resource_type": [
                                        "[\"space\", \"space\"]"
                                    ]
                                },
                                "keysExamined": 3100,
                                "seeks": 1,
                                "dupsTested": 0,
                                "dupsDropped": 0,
                                "seenInvalidated": 0
                            }
                        }
                    }
                }
            }
        ]
    }
}

allPlansExecution

就是把 queryPlanner 和 executionStats 的查询结果汇总起来了

参考

MongoDB查询性能分析(explain) - 梯子教程网

mongo官方 Explain Results

mongo官方 db.collection.explain()