MongoDB干货系列2-MongoDB执行计划分析详解(2)(转载)
写在之前的话
作为近年最为火热的文档型数据库,MongoDB受到了越来越多人的关注,但是由于国内的MongoDB相关技术分享屈指可数,不少朋友向我抱怨无从下手。
《MongoDB干货系列》将从实际应用的角度来进行MongoDB的一些列干货的分享,将覆盖调优,troubleshooting等方面,希望能对大家带来帮助。
如果希望了解更多MongoDB基础的信息,还请大家Google下。
要保证数据库处于高效、稳定的状态,除了良好的硬件基础、高效高可用的数据库架构、贴合业务的数据模型之外,高效的查询语句也是不可少的。那么,如何查看并判断我们的执行计划呢?我们今天就来谈论下MongoDB的执行计划分析。
引子
MongoDB 3.0之后,explain的返回与使用方法与之前版本有了不少变化,介于3.0之后的优秀特色,本文仅针对MongoDB 3.0+的explain进行讨论。
现版本explain有三种模式,分别如下:
queryPlanner
executionStats
allPlansExecution
由于文章字数原因,本系列将分为三个部分。
第一部分
第二部分
第三部分
本文是第二部分,主要是对IndexFilter与Stage进行分析。
正文
IndexFilter
IndexFilter决定了查询优化器对于某一类型的查询将如何使用index,indexFilter仅影响查询优化器对于该类查询可以用尝试哪些index的执行计划分析,查询优化器还是根据分析情况选择最优计划。
如果某一类型的查询设定了IndexFilter,那么执行时通过hint指定了其他的index,查询优化器将会忽略hint所设置index,仍然使用indexfilter中设定的查询计划。
IndexFilter可以通过命令移除,也将在实例重启后清空。
IndexFilter的创建
可以通过如下命令为某一个collection建立indexFilter
db.runCommand(
{
planCacheSetFilter: <collection>,
query: <query>,
sort: <sort>,
projection: <projection>,
indexes: [ <index1>, <index2>, ...]
}
)
db.runCommand(
{
planCacheSetFilter: "orders",
query: { status: "A" },
indexes: [
{ cust_id: 1, status: 1 },
{ status: 1, order_date: -1 }
]
}
)
上图针对orders表建立了一个indexFilter,indexFilter指定了对于orders表只有status条件(仅对status进行查询,无sort等)的查询的indexes,故下图的查询语句的查询优化器仅仅会从{cust_id:1,status:1}
和{status:1,order_date:-1}
中进行winning plan的选择
db.orders.find( { status: "D" } )
db.orders.find( { status: "P" } )
indexFilter的列表
可以通过如下命令展示某一个collecton的所有indexFilter
db.runCommand( { planCacheListFilters: <collection> } )
indexFilter的删除
可以通过如下命令对IndexFilter进行删除
db.runCommand(
{
planCacheClearFilters: <collection>,
query: <query pattern>,
sort: <sort specification>,
projection: <projection specification>
}
)
Stage的意义
如explain.queryPlanner.winningPlan.stage和explain.queryPlanner.winningPlan.inputStage等。
文档中仅有如下几类介绍
COLLSCAN
全表扫描
IXSCAN
索引扫描
FETCH
根据索引去检索指定document
SHARD_MERGE
将各个分片返回数据进行merge
但是根据源码中的信息,个人还总结了文档中没有的如下几类(常用如下,由于是通过源码查找,可能有所遗漏)
SORT
表明在内存中进行了排序(与老版本的scanAndOrder:true一致)
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的返回
部分源码如下:
mongo/jstests/libs/analyze_plan.js
/**
* A query is covered iff it does *not* have a FETCH stage or a COLLSCAN.
*
* Given the root stage of explain's BSON representation of a query plan ('root'),
* returns true if the plan is index only. Otherwise returns false.
*/
function isIndexOnly(root) {
return !planHasStage(root, "FETCH") && !planHasStage(root, "COLLSCAN");
}
/**
* Returns true if the BSON representation of a plan rooted at 'root' is using
* an index scan, and false otherwise.
*/
function isIxscan(root) {
return planHasStage(root, "IXSCAN");
}
/**
* Returns true if the BSON representation of a plan rooted at 'root' is using
* the idhack fast path, and false otherwise.
*/
function isIdhack(root) {
return planHasStage(root, "IDHACK");
}
/**
* Returns true if the BSON representation of a plan rooted at 'root' is using
* a collection scan, and false otherwise.
*/
function isCollscan(root) {
return planHasStage(root, "COLLSCAN");
}
/**
* Get the number of chunk skips for the BSON exec stats tree rooted at 'root'.
*/
function getChunkSkips(root) {
if (root.stage === "SHARDING_FILTER") {
return root.chunkSkips;
}
else if ("inputStage" in root) {
return getChunkSkips(root.inputStage);
}
else if ("inputStages" in root) {
var skips = 0;
for (var i = 0; i < root.inputStages.length; i++) {
skips += getChunkSkips(root.inputStages[0]);
}
return skips;
}
mongo/jstests/concurrency/fsm_workloads/explain_count.js
$config.states = Object.extend({
explainBasicCount: function explainBasicCount(db, collName) {
var res = db[collName].explain().count();
assertAlways.commandWorked(res);
assertAlways(planHasStage(res.queryPlanner.winningPlan, 'COUNT'));
},
explainCountHint: function explainCountHint(db, collName) {
assertWhenOwnColl(function() {
var res = db[collName].explain()
.find({ i: this.nInserted / 2 })
.hint({ i: 1 }).count();
assertWhenOwnColl.commandWorked(res);
assertWhenOwnColl(planHasStage(res.queryPlanner.winningPlan, 'COUNT'));
assertWhenOwnColl(planHasStage(res.queryPlanner.winningPlan, 'COUNT_SCAN'));
});
mongo/jstests/concurrency/fsm_workloads/explain_find.js
$config.states = Object.extend({
explainLimit: function explainLimit(db, collName) {
var res = db[collName].find().limit(3).explain();
assertAlways.commandWorked(res);
assertAlways(planHasStage(res.queryPlanner.winningPlan, 'LIMIT'));
},
explainBatchSize: function explainBatchSize(db, collName) {
var res = db[collName].find().batchSize(3).explain();
assertAlways.commandWorked(res);
},
explainAddOption: function explainAddOption(db, collName) {
var res = db[collName].explain().find().addOption(DBQuery.Option.exhaust).finish();
assertAlways.commandWorked(res);
},
explainSkip: function explainSkip(db, collName) {
var res = db[collName].explain().find().skip(3).finish();
assertAlways.commandWorked(res);
assertAlways(planHasStage(res.queryPlanner.winningPlan, 'SKIP'));
},
explainSort: function explainSort(db, collName) {
var res = db[collName].find().sort({ i: -1 }).explain();
assertAlways.commandWorked(res);
assertAlways(planHasStage(res.queryPlanner.winningPlan, 'SORT'));
},
/**
* The SubplanStage is used for rooted $or queries. It plans each clause of the $or
* individually, and then creates an overall query plan based on the winning plan from
* each clause.
*
* Uses the MultiPlanStage in order to rank plans for the individual clauses.
*
* Notes on caching strategy:
*
* --Interaction with the plan cache is done on a per-clause basis. For a given clause C,
* if there is a plan in the cache for shape C, then C is planned using the index tags
* obtained from the plan cache entry. If no cached plan is found for C, then a MultiPlanStage
* is used to determine the best plan for the clause; unless there is a tie between multiple
* candidate plans, the winner is inserted into the plan cache and used to plan subsequent
* executions of C. These subsequent executions of shape C could be either as a clause in
* another rooted $or query, or shape C as its own query.
*
* --Plans for entire rooted $or queries are neither written to nor read from the plan cache.
*/
allPlansExecution
顾名思义,allPlansExecution模式是将所有的执行计划均进行executionStats模式的操作,不在此赘述了。
转载自:http://www.mongoing.com/eshu_explain2
MongoDB干货系列2-MongoDB执行计划分析详解(2)(转载)的更多相关文章
- MongoDB执行计划分析详解
要保证数据库处于高效.稳定的状态,除了良好的硬件基础.高效高可用的数据库架构.贴合业务的数据模型之外,高效的查询语句也是不可少的.那么,如何查看并判断我们的执行计划呢?我们今天就来谈论下MongoDB ...
- SQL Server 执行计划操作符详解(3)——计算标量(Compute Scalar)
接上文:SQL Server 执行计划操作符详解(2)--串联(Concatenation ) 前言: 前面两篇文章介绍了关于串联(Concatenation)和断言(Assert)操作符,本文介绍第 ...
- MySQL 执行计划explain详解
MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...
- SQL Server 执行计划操作符详解(2)——串联(Concatenation )
本文接上文:SQL Server 执行计划操作符详解(1)--断言(Assert) 前言: 根据计划,本文开始讲述另外一个操作符串联(Concatenation),读者可以根据这个词(中英文均可)先幻 ...
- SQL Server 执行计划操作符详解(1)——断言(Assert)
前言: 很多很多地方对于语句的优化,一般比较靠谱的回复即使--把执行计划发出来看看.当然那些只看语句就说如何如何改代码,我一直都是拒绝的,因为这种算是纯蒙.根据本人经验,大量的性能问题单纯从语句来看很 ...
- MYSQL EXPLAIN执行计划命令详解(支持更新中)
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本篇是根据官网中的每个一点来翻译.举例.验证的:英语不好,所 ...
- 0912MySQL 执行计划explain详解
转自http://blog.itpub.net/29773961/viewspace-1767044/ 该博客内容是比较全的,虽然写的比较晦涩,多读几遍还是不错的 explain命令是查看查询优化器如 ...
- 学习计划 mysql explain执行计划任务详解
我们在之前已经找到了需要优化的SQL,但是怎么知道它的那些方面需要优化呢? explain就是为了这个使用的. explain显示了 mysql 如何使用索引来处理select语句以及连接表.可以帮助 ...
- wav文件格式分析详解
wav文件格式分析详解 文章转载自:http://blog.csdn.net/BlueSoal/article/details/932395 一.综述 WAVE文件作为多媒体中使用的声波文件格式 ...
随机推荐
- python解决使用镜像源来安装包
一.问题在进行python包安装的时候出现一个问题就是无法进行安装,且出现了如下的错误 报错代码 Retrying (Retry(total=4, connect=None, read=None, r ...
- [SOJ #687]双生串(2019-11-6考试)/[hdu5431]AB String
题目大意 把所有仅包含\(AB\)的字符串按字典序排列,给你一个仅包含\(AB\)的字符串\(S\),然后有\(Q\)个问题,第\(i\)个问题给你\(k_i\),求不是\(S\)的子串中,第\(k_ ...
- [SOJ #686]抢救(2019-11-7考试)/[洛谷P3625][APIO2009]采油区域
题目大意 有一个\(n\times m\)的网格,\((x,y)\)权值为\(a_{x,y}\),要求从中选取三个不相交的\(k\times k\)的正方形使得它们权值最大.\(n,m,k\leqsl ...
- 集合单列--Colletion
集合 学习集合的目标: 会使用集合存储数据 会遍历集合,把数据取出来 掌握每种集合的特性 集合和数组的区别 数组的长度是固定的.集合的长度是可变的. 数组中存储的是同一类型的元素,可以存储基本数据类型 ...
- B树索引最通俗易懂的介绍
先来一段有莫的对话: 前几天下班回到家后正在处理一个白天没解决的bug,厕所突然传来对象的声音: 对象:xx,你有<时间简史>吗? 我:我去!妹子,你这啥癖好啊,我有时间也不会去捡屎 ...
- 正则表达式回溯导致的CPU打满
参考: https://my.oschina.net/ttscjr/blog/2208526 https://mp.weixin.qq.com/s?__biz=MzA4MjIyNTY0MQ==& ...
- 使用国内作者制作的gcr.io镜像安装工具
项目地址:https://github.com/zhangguanzhang/gcr.io How to use? 拉取 假设需要拉取gcr.io/google_containers/pause:3. ...
- nlp学习杂记
什么是 token embedding? 输入一个word,在字典里查找得到它对应的下标就是token,然后用该数字下标去lookup表查找得到该词对应的词向量(词嵌入)就是embedding wor ...
- 锤子剪刀布pat-1018
题目描述 大家应该都会玩“锤子剪刀布”的游戏:现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出什么手势的胜算最大. 输入描述: 输入第1行给出正整数N(<=105),即双方交 ...
- 女性长期没有"恩爱",会出现这4个后果?提醒:频率最好能在这个数
一直以来,很多人认为:男性性欲比女性强! 其实:因人而异! 但不管怎么说,“性”话题在如今社会中已经不再成为隐晦谈资. 越来越多的人,可以把此话题拿到桌面上各抒己见. 总归,“性”是我们探索自我的一种 ...