MongoDB——Explain详解

2,152 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

介绍

explain 是做什么的?如何工作?

分析查询的过程中,执行的最佳情况

  • 可以查询是否使用了期望的索引
  • 索引是否提供了排序
  • 可以提供多种索引的执行计划
  • 统计查询过程中的信息

Mongodb 提供了explain 命令,可以帮我们评估指定查询(querymodel)的执行计划,根据实际情况调整,从而提高查询效率。

如何使用?

我们只需要将explain()方法附加到查询末尾

db.<collection>.find().explain(<verbose>)

verbose可选参数,表示执行计划的输出模式,默认queryPlanner

然后,这种形式有一些限制,假如,存在更复杂的命令,或者需要重新运行多个查询,建议我们创建一个可解释对象,重复使用。

exp = db.<collection>.explain()
exp.find()

这样我们可以解释多个查询,非常方便。

模式

explain 共提供了3种模式,以便我们在不同情况下使用。

queryPlanner模式

执行计划的详细信息,包括查询计划、集合信息、查询条件、最佳执行计划、查询方式和Mongodb服务信息等。

"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>,
      ...
   ]
}
key描述
queryPlanner.planerVersion执行计划的版本
queryPlanner.namespace命名空间,包含数据库名称和集合名称(<database>.<collection>.
queryPlanner.indexFilterSet是否使用了索引
queryPlanner.parsedQuery查询条件
queryPlanner.queryHash查询的一个哈希值,帮助职别具有相同查询的慢查询,这块不同擦护心发生哈希冲突的情况可能性很小。
queryPlanner.planCacheKey与查询关联的计划缓存键的哈希
queryPlanner.optimizedPipeline表示整个聚合管道操作是否被优化掉,一些简单的查询,会被优化,而不是使用聚合来做。比如:管道中只有一个$match
queryPlanner.winningPlan选择的执行计划,将以树的形式展现;每一个阶段可以有一个inputStage ,如果阶段有多个子阶段,则会返回多个。
queryPlanner.winningPlan.stage表示当前阶段的查询方式
queryPlanner.winningPlan.inputStage子阶段的执行情况,子阶段向父阶段会提供文档或索引键。
queryPlanner.winningPlan.inputStages一组子阶段的执行情况
queryPlanner.rejectedPlans拒绝的执行计划

exectionStats模式和allPlansExecution 模式

都可以返回最佳的执行计划,allPlansExecution模式相比较多了其他的执行计划。

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: {
            ...
         }
      }
   },
   allPlansExecution: [
      {
         nReturned: <int>,
         executionTimeMillisEstimate: <int>,
         totalKeysExamined: <int>,
         totalDocsExamined:<int>,
         executionStages: {
            stage: <STAGEA>,
            nReturned: <int>,
            executionTimeMillisEstimate: <int>,
            ...
            inputStage: {
               stage: <STAGEB>,
               ...
               inputStage: {
                 ...
               }
            }
         }
      },
      ...
   ]
}
key描述
executionStats.nReturned符合条件的文档数,旧版本中的:n
executionStats.executionTimeMillis解释和查询执行的总时间,单位:毫秒,旧版本的millis
executionStats.totalKeysExamined扫描索引键数目,旧版本的nscanned
executionStats.totalDocsExamined扫描的文档数目。不代表返回的文档数,而且并不是只扫描一次,可能在不同的步骤扫描多次。
executionStats.executionStages执行情况
executionStats.executionStages.executionTimeMillisEstimate查询的一个预估时间,单位:毫秒
executionStats.executionStages.opensMongoDB 5.1 开始,在查询执行期间打开阶段的次数。
executionStats.executionStages.closesMongoDB 5.1 开始,在查询执行期间关闭阶段的次数。
executionStats.executionStages.works查询阶段中执行的“工作单元”数量,可能包括索引键、文档等。
executionStats.executionStages.saveState查询阶段暂停处理并保存起当前执行状态的次数,例如准备释放其锁的次数
executionStats.executionStages.restoreState查询阶段恢复保存的执行状态的次数,例如在恢复它之前产生的锁之后。
executionStats.executionStages.isEOF执行阶段是否到达流的尾部:
1true:表示到达,即一次执行完成
0false:表示未到达,该阶段可能仍有结果要返回。例如,考虑一个具有限制的查询,其执行阶段由一个阶段组成,该LIMIT阶段的输入阶段IXSCAN为 。如果查询返回超过指定限制,该LIMIT阶段将报告isEOF: 1,但其底层IXSCAN阶段将报告isEOF: 0。
explain.executionStats.executionStages.inputStage描述子文档
executionStats.allPlansExecution所有的执行计划。