QuerySolution 执行计划(过滤条件filter、sort排序等都属于计划的一部分)
QueryPlaner 生成执行计划模块(explain()生成执行计划,不实际执行)
PlanExecutor 运行执行计划模块,同时充当优化器(Optimizer)的角色(explain(executionStats)实际运行执行计划)

- 1). Client按照MongoDB的网络协议,请求建立连接,并友单独新建的thread处理所有请求。
- 2). 有些Query(如insert),本身不需要执行计划和优化,这直接通过接口和引擎交互(通过RecordStore写表)
- 3). Query会进行简单的处理(标准化),并构造一些上下文数据结构变成CanonicalQuery(标准化Query)。
- 4). Plan模块会负责生成该Query的多个执行计划,然后丢给Optimizer去选择最优的,丢给PlanExecutor。
- 5). PlanExecutor按照执行计划一步一步迭代,获得最终的数据(或执行update修改数据)。
在此流程中: - Plan如果只关联到单个或零个索引,这只生成一个执行计划,如果发现有多个索引或者索引有重叠,这可能生成多个执行计划。
- Optimizer只在多个执行计划时,才会介入。
explain() 可以接收不同的参数,通过设置不同参数我们可以查看更详细的查询计划。
queryPlanner:是默认参数
explain() 设置参数的三种模式
1 queryPlanner
不会真正的执行查询,只是分析查询,选出winning plan。
2 executionStats
返回winning plan的关键数据。
executionTimeMillis该query查询的总体时间。
3 allPlansExecution
执行所有的plans。
> db.getCollection("stepsDetail").find( { "ssoid" : "670274649", "modifiedTime" : NumberLong(1619671871306) } ).explain(){"queryPlanner" : {"mongosPlannerVersion" : 1,"winningPlan" : {"stage" : "SINGLE_SHARD","shards" : [{"shardName" : "sport-health_oXHqoVcC_shard_2", //分片"connectionString" : "sport-health_oXHqoVcC_shard_2/10.177.233.79:20000,10.177.233.80:20000,10.177.233.81:20000",//链接字符串"serverInfo" : { //MongoDB服务器信息"host" : "10-177-233-81.mongodb-fatpod-sport-health.dgtest01","port" : 20000,"version" : "3.6.13","gitVersion" : "db3c76679b7a3d9b443a0e1b3e45ed02b88c539f"},"plannerVersion" : 1, //查询计划版本"namespace" : "sporthealth.stepsDetail", //要查询的集合"indexFilterSet" : false, //boolean 查询模型是否使用索引过滤"parsedQuery" : {//查询条件"$and" : [{"modifiedTime" : {"$eq" : NumberLong("1619671871306")}},{"ssoid" : {"$eq" : "670274649"}}]},"winningPlan" : { //最佳执行计划"stage" : "FETCH",//最优执行计划的stage"inputStage" : {"stage" : "IXSCAN",//查询方式,常见的有COLLSCAN/全表扫描、IXSCAN/索引扫描、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询"keyPattern" : {//所扫描的index内容"ssoid" : 1,"modifiedTime" : -1},"indexName" : "ssoid_1_modifiedTime_-1",//winning plan所选用的index"isMultiKey" : false,//是否是Multikey,此处返回是false,如果索引建立在array上,此处将是true。"multiKeyPaths" : {"ssoid" : [ ],"modifiedTime" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward",//此query的查询顺序,此处是forward,如果用了.sort({ssoid:-1})将显示backward。"indexBounds" : {//winningplan所扫描的索引范围"ssoid" : ["[\"670274649\", \"670274649\"]"],"modifiedTime" : ["[1619671871306, 1619671871306]"]}}},"rejectedPlans" : [//其他执行计划(非最优而被查询优化器reject的)的详细返回,其中具体信息与winningPlan的返回中意义相同{"stage" : "FETCH","filter" : {//过滤条件"$and" : [{"ssoid" : {"$eq" : "670274649"}},{"modifiedTime" : {"$eq" : NumberLong("1619671871306")}}]},"inputStage" : {"stage" : "IXSCAN","keyPattern" : {//所扫描的index内容"ssoid" : "hashed"},"indexName" : "ssoid_hashed",//所选用的index"isMultiKey" : false,"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"ssoid" : ["[-6533328432691190449, -6533328432691190449]"]}}},{"stage" : "FETCH","filter" : { //过滤条件"modifiedTime" : {"$eq" : NumberLong("1619671871306")}},"inputStage" : {"stage" : "IXSCAN","keyPattern" : { //所扫描的index内容"ssoid" : 1,"clientDataId" : 1},"indexName" : "ssoid_1_clientDataId_1","isMultiKey" : false,"multiKeyPaths" : {"ssoid" : [ ],"clientDataId" : [ ]},"isUnique" : true,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"ssoid" : ["[\"670274649\", \"670274649\"]"],"clientDataId" : ["[MinKey, MaxKey]"]}}}]}]}},"ok" : 1, //操作状态"operationTime" : Timestamp(1619683463, 3),////操作时间"$clusterTime" : {"clusterTime" : Timestamp(1619683468, 1),"signature" : {"hash" : BinData(0,"uCHZd6sSRBNKDLXw1xUi2mHErmo="),"keyId" : NumberLong("6915417759157321730")}}}
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的返回
> db.getCollection("stepsDetail").find({"ssoid" : "670274649","modifiedTime" : NumberLong(1619671871306) } ).explain("executionStats")"executionStats" : {"nReturned" : 27,//查询的返回条数"executionTimeMillis" : 1,//整体执行时间"totalKeysExamined" : 27,//索引扫描次数"totalDocsExamined" : 27,//document扫描次数"executionStages" : {"stage" : "SINGLE_SHARD","nReturned" : 27,//返回27条数据"executionTimeMillis" : 1,//该查询根据index去检索document获取27条具体数据的时间"totalKeysExamined" : 27,//索引扫描次数"totalDocsExamined" : 27,//document扫描次数"totalChildMillis" : NumberLong(1),"shards" : [{"shardName" : "sport-health_oXHqoVcC_shard_2","executionSuccess" : true,"executionStages" : {"stage" : "FETCH","nReturned" : 27,"executionTimeMillisEstimate" : 0,"works" : 29,"advanced" : 27,"needTime" : 0,"needYield" : 0,"saveState" : 0,"restoreState" : 0,"isEOF" : 1,"invalidates" : 0,"docsExamined" : 27,"alreadyHasObj" : 0,"inputStage" : {"stage" : "IXSCAN", //扫描方式"nReturned" : 27, //查询结果数量"executionTimeMillisEstimate" : 0, //预估耗时"works" : 28, //工作单元数,一个查询会分解成小的工作单元"advanced" : 27, //优先返回的结果数"needTime" : 0,"needYield" : 0,"saveState" : 0,"restoreState" : 0,"isEOF" : 1,"invalidates" : 0,"keyPattern" : { //索引"ssoid" : 1,"modifiedTime" : -1},"indexName" : "ssoid_1_modifiedTime_-1","isMultiKey" : false,"multiKeyPaths" : {"ssoid" : [ ],"modifiedTime" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"ssoid" : ["[\"670274649\", \"670274649\"]"],"modifiedTime" : ["[1619671871306, 1619671871306]"]},"keysExamined" : 27,"seeks" : 1,"dupsTested" : 0,"dupsDropped" : 0,"seenInvalidated" : 0}}}]}}
