线上讲座:MongoDB DBA的日常巡检及执行计划分析 (2)

 

活动工夫:12月19日 ~

活动地点:上海市徐汇区虹桥路3号港汇中心2座10层(微软中国)

活动主题:洞察-发现数据的力量

越来越多的人说,“人类正在从IT时代走向DT时代。”在这样一个以数据处理技术为驱动的时期,技术从IT时代的自我控制与自我管理,转变到现在的服务大众与激发生产力上,从信息到数据,这实现了一个跨越。技术需要推动,思维需要变革,社会需要创新,因此,这成为充满创造精神的开发者们一个最好的年代。

数据需要交叉才能产生更多价值,开发者及企业都希望能更好的处理数据,在大数据的普及过程中,“存储”、“流通”、“处理”一直存在,如何发现数据的更多力量?本次沙龙将会为大家分享基于IAAS、PASS等云服务如何构建数据平台,以及分享自身在数据分析及处理方面使用的应用与实战经验。

活动流程:

工夫内容分享者– 入场及签到基于云服务构建弹性大数据处理平台孙辉(聚合数据高级产品经理) – 数据时代的云应用王盛麟(微软资深云计算技术战略顾问)– 茶歇交流Teambition 数据分析工具链纪杨(Teambition数据分析师) – 基于PaaS构建数据平台沈阅斌(Anchora产品研发总监) – 圆桌对话+Q&A(抽奖环节)

分享嘉宾:

孙辉(聚合数据高级产品经理):

近10年互联网行业工作经验,从事与电商、大数据相关行业的研发、产品设计工作。在此期间,参与设计与研发了多套电商、大数据服务行业系统。现任聚合数据高级产品经理,全面负责聚合数据产品线工作。

王盛麟(Austin Wang)(微软资深云计算技术战略顾问):

法国马赛商学院工商管理学硕士,微软(中国)有限公司资深云计算技术战略顾问,华东区云计算领导者专注于企业云计算策略研究,机构规划以及落地实施。同时也是企业信息化架构专家,对大中型企业基础架构,协作架构以及应用架构建设有着丰富的规划,设计以及实施经验。同时著有畅销两岸三地的“windows7使用详解”以及“Office365使用详解”工具书。

纪杨(Teambition数据分析师):

Teambition 数据分析师,负责公司业务、流量数据分析,为产品,市场,销售等部门提供数据支持。前程序员,之前在沪江网,华住酒店集团从事数据分析工作,有丰富的网站数据分析,用户体验分析经验,个人博客:jiyang.me

沈阅斌(Anchora产品研发总监)

目前在Anchora负责云计算平台产品研发和管理工作。先后在多家软件公司担任项目研发、项目管理及技术培训等工作。对企业应用开发、大型网站架构、云计算、大数据等领域有相关实践经验。对Cloudfoundry、Openstack、CloudStack、Hadoop等开源云技术进行研究和使用。目前担任Anchora产品研发总监,主要负责PaaS产品的研发。

作为近年最为火热的文档型数据库,MongoDB受到了越来越多人的关注,但是由于国内的MongoDB相关技术分享屈指可数,不少朋友向我抱怨无从下手。

《MongoDB干货系列》将从实际应用的角度来进行MongoDB的一些列干货的分享,将覆盖调优,troubleshooting等方面,希望能对大家带来帮助。

如果希望了解更多MongoDB基础的信息,还请大家Google下。

要保证数据库处于高效、稳定的状态,除了良好的硬件基础、高效高可用的数据库架构、贴合业务的数据模型之外,高效的查询语句也是不可少的。那么,如何查看并判断我们的执行计划呢?我们今天就来谈论下MongoDB的执行计划分析。

引子

MongoDB 3.0之后,explain的返回与使用方法与之前版本有了不少变化,介于3.0之后的优秀特色,本文仅针对MongoDB 3.0+的explain进行讨论。

现版本explain有三种模式,分别如下:

  • queryPlanner
  • executionStats
  • allPlansExecution

由于文章字数原因,本系列将分为三个部分。
第一部分
第二部分
第三部分

本文是第一部分,主要针对queryPlanner,与executionStats进行分析。

正文

queryPlanner

queryPlanner是现版本explain的默认模式,queryPlanner模式下并不会去真正进行query语句查询,而是针对query语句进行执行计划分析并选出winning plan。

{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "game_db.game_user",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "w" : {
                                "$eq" : 1
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "w" : 1,
                                        "n" : 1
                                },
                                "indexName" : "w_1_n_1",
                                "isMultiKey" : false,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "w" : [
                                                "[1.0, 1.0]"
                                        ],
                                        "n" : [
                                                "[MinKey, MaxKey]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [
                        {
                                "stage" : "FETCH",
                                "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "keyPattern" : {
                                                "w" : 1,
                                                "v" : 1
                                        },
                                        "indexName" : "w_1_v_1",
                                        "isMultiKey" : false,
                                        "direction" : "forward",
                                        "indexBounds" : {
                                                "w" : [
                                                        "[1.0, 1.0]"
                                                ],
                                                "v" : [
                                                        "[MinKey, MaxKey]"
                                                ]
                                        }
                                }
                        }
                ]
        },

先来看queryPlanner模式的各个返回意义。

explain.queryPlanner

queryPlanner的返回。

explain.queryPlanner.namespace

顾名思义,该值返回的是该query所查询的表。

explain.queryPlanner.indexFilterSet

针对该query是否有indexfilter(会在后文进行详细解释)。

explain.queryPlanner.winningPlan

查询优化器针对该query所返回的最优执行计划的详细内容。

explain.queryPlanner.winningPlan.stage

最优执行计划的stage,这里返回是FETCH,可以理解为通过返回的index位置去检索具体的文档(stage有数个模式,将在后文中进行详解)。

explain.queryPlanner.winningPlan.inputStage

explain.queryPlanner.winningPlan.stage的child stage,此处是IXSCAN,表示进行的是index scanning。

explain.queryPlanner.winningPlan.keyPattern

所扫描的index内容,此处是w:1与n:1。

explain.queryPlanner.winningPlan.indexName

winning plan所选用的index。

explain.queryPlanner.winningPlan.isMultiKey

是否是Multikey,此处返回是false,如果索引建立在array上,此处将是true。

explain.queryPlanner.winningPlan.direction

此query的查询顺序,此处是forward,如果用了.sort({w:-1})将显示backward。

explain.queryPlanner.winningPlan.indexBounds

winningplan所扫描的索引范围,此处查询条件是w:1,使用的index是w与n的联合索引,故w是[1.0,1.0]而n没有指定在查询条件中,故是[MinKey,MaxKey]。

explain.queryPlanner.rejectedPlans

其他执行计划(非最优而被查询优化器reject的)的详细返回,其中具体信息与winningPlan的返回中意义相同,故不在此赘述。

executionStats

executionStats的返回中多了如下:

  "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 29861,
                "executionTimeMillis" : 23079,
                "totalKeysExamined" : 29861,
                "totalDocsExamined" : 29861,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 29861,
                        "executionTimeMillisEstimate" : 22685,
                        "works" : 29862,
                        "advanced" : 29861,
                        "needTime" : 0,
                        "needFetch" : 0,
                        "saveState" : 946,
                        "restoreState" : 946,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "docsExamined" : 29861,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 29861,
                                "executionTimeMillisEstimate" : 70,
                                "works" : 29862,
                                "advanced" : 29861,
                                "needTime" : 0,
                                "needFetch" : 0,
                                "saveState" : 946,
                                "restoreState" : 946,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "keyPattern" : {
                                        "w" : 1,
                                        "n" : 1
                                },
                                "indexName" : "w_1_n_1",
                                "isMultiKey" : false,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "w" : [
                                                "[1.0, 1.0]"
                                        ],
                                        "n" : [
                                                "[MinKey, MaxKey]"
                                        ]
                                },
                                "keysExamined" : 29861,
                                "dupsTested" : 0,
                                "dupsDropped" : 0,
                                "seenInvalidated" : 0,
                                "matchTested" : 0
                        }
                }
        },

executionStats模式中,我们主要需要注意的返回有如下几个

executionStats.executionSuccess

是否执行成功

executionStats.nReturned

查询的返回条数

executionStats.executionTimeMillis

整体执行时间

executionStats.totalKeysExamined

索引扫描次数

executionStats.totalDocsExamined

document扫描次数

以上几个非常好理解,我们就不在这里详述,后文的案例中会有分析。

executionStats.executionStages.stage

这里是FETCH去扫描对于documents

executionStats.executionStages.nReturned

由于是FETCH,所以这里该值与executionStats.nReturned一致

executionStats.executionStages.docsExamined

与executionStats.totalDocsExamined一致

executionStats.inputStage中的与上述理解方式相同

还有一些文档中没有描述的返回如:

“works” : 29862,

“advanced” : 29861,

“isEOF” : 1,

这些值都会在explan之初初始化:

mongo/src/mongo/db/exec/plan_stats.h

struct CommonStats {
    CommonStats(const char* type)
        : stageTypeStr(type),
          works(0),
          yields(0),
          unyields(0),
          invalidates(0),
          advanced(0),
          needTime(0),
          needYield(0),
          executionTimeMillis(0),
          isEOF(false) {}

以works为例,查看源码中发现,每次操作会加1,且会把执行时间记录在executionTimeMillis中。

mongo/src/mongo/db/exec/fetch.cpp

         ++_commonStats.works;

        // Adds the amount of time taken by work() to executionTimeMillis.
        ScopedTimer timer(&_commonStats.executionTimeMillis);

而在查询结束EOF,works又会加1,advanced不加。

mongo/src/mongo/db/exec/eof.cpp

PlanStage::StageState EOFStage::work(WorkingSetID* out) {
    ++_commonStats.works;
    // Adds the amount of time taken by work() to executionTimeMillis.
    ScopedTimer timer(&_commonStats.executionTimeMillis);
    return PlanStage::IS_EOF;
}

故正常的返回works会比nReturned多1,这时候isEOF为true(1):

mongo/src/mongo/db/exec/eof.cpp

bool EOFStage::isEOF() {
    return true;
}

unique_ptr<PlanStageStats> EOFStage::getStats() {
    _commonStats.isEOF = isEOF();
    return make_unique<PlanStageStats>(_commonStats, STAGE_EOF);
}

advanced的返回值在命中的时候+1,在skip,eof的时候不会增加如:

mongo/src/mongo/db/exec/skip.cpp

if (PlanStage::ADVANCED == status) {
        // If we're still skipping results...
        if (_toSkip > 0) {
            // ...drop the result.
            --_toSkip;
            _ws->free(id);
            ++_commonStats.needTime;
            return PlanStage::NEED_TIME;
        }

        *out = id;
        ++_commonStats.advanced;
        return PlanStage::ADVANCED;

后文

 

 

相关文章