MongoDB索引Index应用之explain()方法
与MySQL(参考MySQL索引原理之索引分析 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com))一样,MongoDB也提供explain命令对索引进行分析。那如何使用MongoDB中的explain命令呢?下面进行实践:
与MySQL中explain实践(参考Explain Results — MongoDB Manual)类似循环插⼊100万条数据(使用JS),不使⽤索引字段查询查看执⾏计划 ,然后给某个字段建⽴索引,使⽤索引字段作为查询条件再查看执⾏计划进⾏分析:
插入200万条数据——与MySQL一样,想着MongoDB是不是也提供存储过程功能,确实提供了只是利用了JS。本以为可以参考在mongodb服务器上存储和执行 js 函数 - 存储过程 - 知乎 (zhihu.com)写存储过程insert100万条数据,但是存储过程的调用eval在MongoDB4.2以后版本就完全弃用了——官方的建议是使用事务取而代之,可以看到官网中提供的Database Command已经没有了evalDatabase Commands — MongoDB Manual,那就采取另外一种方式吧。如下:
为后续查询分析准备不再使用默认_id,使用自定义_id,可以参考MongoDB 自动增长 | 菜鸟教程 (runoob.com)。
getNextSequence方法是通过db.system.js.insert直接放在system.js表中的。为什么是这个表而不是其他的呢?因为这个表是专门用来保存js函数的。如果定义完函数退出mongo实例,会发现还是无法使用函数getNextSequence。这是因为虽然定义了函数但是没有把函数引入仍然无法使用,也就是说每次重新进入mongo的实例后需要把相应的js函数重新导入一遍。通过,db.loadServerScripts();把system.js中的函数,引入到mongo实例
下面示范explain的使用:
从上图可知explain()可以接收不同的参数,通过设置不同参数我们可以查看更详细的查询计划,分别如下:
1、queryPlanner: queryPlanner是默认参数。
2、executionStats: executionStats会返回执⾏计划的⼀些统计信息(有些版本中和allPlansExecution等同)。
第⼀层, executionTimeMillis最为直观explain返回值是executionTimeMillis值,指的是这条语句的执⾏时间,这个值当然是希望越少越好。其中有3个executionTimeMillis,分别是:
executionStats.executionTimeMillis 该query的整体查询时间。
executionStats.executionStages.executionTimeMillisEstimate 该查询检索document获得数据的时间。
executionStats.executionStages.inputStage.executionTimeMillisEstimate 该查询扫描⽂档 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运算
TEXT:使⽤全⽂索引进⾏查询时候的stage返回
PROJECTION:限定返回字段时候stage的返回
对于普通查询,最希望看到stage的组合(查询的时候尽可能⽤上索引):
Fetch+IDHACK
Fetch+IXSCAN
Limit+(Fetch+IXSCAN)
PROJECTION+IXSCAN
SHARDING_FITER+IXSCAN
不希望看到包含如下的stage:
COLLSCAN(全表扫描)
SORT(使⽤sort但是⽆index)
COUNT 不使⽤index进⾏count)
3、allPlansExecution:allPlansExecution⽤来获取所有执⾏计划,结果参数基本与上⽂相同。其是以上两个参数的拼接。
explain方法展示执行计划采用树结构,如图: