专栏首页MongoDB中文社区mongoDB 3.0+ 查询性能分析

mongoDB 3.0+ 查询性能分析

mongoDB性能分析方法:explain()

为了演示的效果,我们先来创建一个有200万个文档的记录。(我自己的电脑耗了15分钟左右插入完成。如果你想插更多的文档也没问题,只要有耐心等就可以了。)

for(var i=0;i<2000000;i++){
    db.person.insert({"name":"ryan"+i,"age":i});
}

mongoDB 3.0之后,explain的返回与使用方法与之前版本有了很大的变化,介于3.0之后的优秀特色和我们目前所使用给的是3.0.7版本,本文仅针对mongoDB 3.0+的explain进行讨论。3.0+的explain有三种模式,分别是:queryPlanner、executionStats、allPlansExecution。现实开发中,常用的是executionStats模式,主要分析这种模式。

给这个person集合创建age键的索引:

db.person.createIndex({"age":1})

然后我们用explain()来看看具体的执行计划

db.getCollection('person')
  .find({"age":{"$lte":2000}})
  .explain("executionStats")

对queryPlanner分析

queryPlanner: queryPlanner的返回

queryPlanner.namespace:该值返回的是该query所查询的表

queryPlanner.indexFilterSet:针对该query是否有indexfilter

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

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

queryPlanner.winningPlan.inputStage:用来描述子stage,并且为其父stage提供文档和索引关键字。

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

queryPlanner.winningPlan.keyPattern:所扫描的index内容,此处是did:1,status:1,modify_time: -1与scid : 1

queryPlanner.winningPlan.indexName:winning plan所选用的index。

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

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

queryPlanner.winningPlan.indexBounds:winningplan所扫描的索引范围,如果没有制定范围就是[MaxKey, MinKey],这主要是直接定位到mongodb的chunck中去查找数据,加快数据读取。

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

对executionStats返回逐层分析

第一层,executionTimeMillis

最为直观explain返回值是executionTimeMillis值,指的是我们这条语句的执行时间,这个值当然是希望越少越好。

其中有3个executionTimeMillis,分别是:

executionStats.executionTimeMillis该query的整体查询时间。

executionStats.executionStages.executionTimeMillisEstimate该查询根据index去检索document获得2001条数据的时间。

executionStats.executionStages.inputStage.executionTimeMillisEstimate该查询扫描2001行index所用时间。

第二层,index与document扫描数与查询返回条目数

这个主要讨论3个返回项,nReturned、totalKeysExamined、totalDocsExamined,分别代表该条查询返回的条目、索引扫描条目、文档扫描条目。

这些都是直观地影响到executionTimeMillis,我们需要扫描的越少速度越快。

对于一个查询,我们最理想的状态是:nReturned=totalKeysExamined=totalDocsExamined

第三层,stage状态分析

那么又是什么影响到了totalKeysExamined和totalDocsExamined?是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的返回

对于普通查询,我希望看到stage的组合(查询的时候尽可能用上索引):

Fetch+IDHACK

Fetch+ixscan

Limit+(Fetch+ixscan)

PROJECTION+ixscan

SHARDING_FITER+ixscan

COUNT_SCAN

不希望看到包含如下的stage:

COLLSCAN(全表扫描),SORT(使用sort但是无index),不合理的SKIP,SUBPLA(未用到index的$or),COUNTSCAN(不使用index进行count)

END

作者:周钦雄,热衷分享,拥抱开源的程序员。本文经授权转载自微信公众号:精修Java。

本文分享自微信公众号 - Mongoing中文社区(mongoing-mongoing)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-01-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 海量数据的分页怎么破?

    分页应该是极为常见的数据展现方式了,一般在数据集较大而无法在单个页面中呈现时会采用分页的方法。

    MongoDB中文社区
  • 官宣 | MongoDB面向MongoDB社区版发布全新服务器端公共许可协议

    MongoDB 公司(Nasdaq代码:MDB)日前发布了一项全新的面向 MongoDB 社区版的软件许可证,即服务器端公共许可证(SSPL)。该许可协议清晰且...

    MongoDB中文社区
  • 事务,时间戳与混合逻辑时钟

    这篇文章接上文mongodb4.0事务实现浅析。 mongo从3.6之后,开始进行WT-TIMESTAMP-PROJ,后续server层引入了带签名的逻辑时钟l...

    MongoDB中文社区
  • GO-操作数据库

    Go 语言中的 database/sql 包定义了对数据库的一系列操作。database/sql/driver包定义了应被数据库驱动实现的接口,这些接口会被 s...

    cwl_java
  • 真正掌握vuex的使用方法(四)

    是不是很长?是不是看着它很蓝瘦? 正常的第一反应就是将其写入到计算属性内,方便调用!所以咱们可以将computed调整如下:

    用户1272076
  • 实践 -实现一款中间凸起的TabBar

    这是看到一篇文章后感觉很有意思于是就把自己的效果改了改实现了一下,文末有原文链接。

    進无尽
  • Python学习 :反射 & 单例模式

      - 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。

    py3study
  • Python采用并发查询mysql以及调用API灌数据 (三)- Python跨文件目录引入类方法

    本次因为服务架构重构,表优化、重构,带来的任务就是需要从原来的mysql数据库中,读取原表数据(部分存在多张关联查询)然后通过调用API的服务方式灌入新的数据库...

    Devops海洋的渔夫
  • HIVE入门_2

    HIVE 是数据仓库,本质上也是数据库。 数据仓库 概念 就是一个数据库。 数据仓库是一个面向主题的(商品的推荐系统内容是商品的信息)、集成的(分散型地...

    用户1147754
  • CentOS 8设置自动更新的完整步骤

    你可以为数据和计算机做的最好的事情就是确保它们的安全。就像打开更新一样简单,但是,大多数使用CentOS 8的人都不知道该怎么做。

    砸漏

扫码关注云+社区

领取腾讯云代金券