MongoDB查询计划explain

MongoDB查询计划explain

MongoDB 中的 explain() 函数可以帮助我们查看查询相关的信息,这有助于我们快速查找到搜索瓶颈进而解决它。整体来说,explain() 的用法和 sort()、 limit() 用法差不多,不同的是 explain() 必须放在最后面。

MongoDB查询计划explain详解

语法

db_name.table_Name.find({query}).explain(cond)

参数

名称 描述
db_name 数据库名
table_Name 集合名
query 查询条件
cond 查询计划所使用的参数

返回值

参数 含义
plannerVersion 查询计划版本
namespace 要查询的集合
indexFilterSet 是否使用索引
parsedQuery 查询条件,此处为x=1
winningPlan 最佳执行计划
stage 查询方式,见下表
filter 过滤条件
direction 搜索方向
rejectedPlans 拒绝的执行计划
serverInfo MongoDB服务器信息

stage说明

参数 含义
COLLSCAN 全表扫描
IXSCAN 索引扫描
FETCH 根据索引去检索文档
SHARD_MERGE 合并分片结果
IDHACK 针对 _id 进行查询

Sort阶段

如果 MongoDB 可以使用索引扫描来获取请求的排序顺序,则结果将不包括 SORT 阶段。 否则,如果 MongoDB 无法使用索引进行排序,则解释结果将包括 SORT 阶段。

在 MongoDB 3.0 之前,cursor.explain() 返回 scanAndOrder 字段以指定 MongoDB 是否可以使用索引顺序返回排序结果。

explain希望看到的阶段

  1. Fetch+IDHACK
  2. Fetch+ixscan
  3. Limit+(Fetch+ixscan)
  4. PROJECTION+ixscan
  5. SHARDING_FILTER+ixscan
  6. COUNT_SCAN

explain不希望看到的阶段

  1. COLLSCAN(全表扫描)
  2. SORT(使用sort但是无index)
  3. 不合理的SKIP
  4. SUBPLA(未用到index的$or)
  5. COUNTSCAN

案例

我们首先,使用 mongo 命令,连接上数据库,具体命令如下:

mongo

如下图所示:

65_MongoDB查询计划explain.png

现在,我们使用 use 命令,切换到 haicoder 数据库,具体命令如下:

use haicoder

现在,我们使用 insert 插入四条记录,具体命令如下:

db.haicoder.insert([ {id:1, "url" : "haicoder.net/c", "score" : 100 }, {id:2, "url" : "haicoder.net/cpp", "score" : 90 }, {id:3, "url" : "haicoder.net/golang", "score" : 80 }, {id:4, "url" : "haicoder.net/java", "score" : 60 } ]);

执行完毕后,此时,如下图所示:

66_MongoDB查询计划explain.png

我们看到,此时提示我们成功插入了多条记录,现在,我们使用 find 查询并查看执行计划,具体命令如下:

db.haicoder.find({score:80}).explain();

执行完毕后,此时,如下图所示:

67_MongoDB查询计划explain.png

我们看到,这里并没有使用任何索引,因为返回的 indexFilterSet 字段的值为 false,并且 stage 为 COLLSCAN 即全表扫描了。现在,我们创建一个索引,具体命令如下:

db.haicoder.createIndex({score:1})

执行完毕后,此时如下图所示:

68_MongoDB查询计划explain.png

现在,我们再次查询,此时,如下图所示:

69_MongoDB查询计划explain.png

我们看到,此时是使用了索引去检索文档,返回的 stage 为 FETCH。

MongoDB查询计划explain总结

MongoDB 中的 explain() 函数可以帮助我们查看查询相关的信息,这有助于我们快速查找到搜索瓶颈进而解决它。整体来说,explain() 的用法和 sort()、 limit() 用法差不多,不同的是 explain() 必须放在最后面。