无论是mysql
还是mongo
,数据库是一个系统最容易出现问题、瓶颈的地方。mysql
出现问题时,相信大家都有一套完善的调试、调优方法,从最基础的查看slow log
,query log
到mysql explain
查询索引分析等;而由于在mongo
方面的技术积累没有mysql
那么多,出现性能问题时,往往需要去花很大的精力进行调优。
索引
mongo
中的索引跟mysq
l中索引同样重要,没有索引,每次查找都需要遍历全表。
mongo
的索引类型包括如下几种:
single filed
索引:最基本的索引类型,加在单个filed
上,可以指定升降序,默认_id列会自动加上该索引
Compound Index
:复合索引加在多个field
上,每一个字段都可以指定升降序;复合索引的顺序比较重要,它决定了该索引操作是否支持排序Multikey Index
:如果给array
类型的field
加索引,mongo
会自动创建一个multikey index
Geospatial Index
:地理空间索引Text Indexes
: 一个集合最多只能够创建一个文本索引,文本索引加在string类型的列上Hashed Index
索引的一些特征:
unique index
:指定为唯一索引Partial Index
:索引只会加到特定条件的document
上,用户可以指定过滤条件Sparse Index
:索引会跳过所有不包含被索引键的文档。这个索引之所以称为 “稀疏” 是因为它并不包括集合中的所有文档TTL Index
:通过TTL索引,mongo
会在过一段时间以后自动删除集合中的文档
Mongo explain
与mysql
相同,mongo
也可以通过使用explain
命令来查看mongo
的执行情况,不同的是mongo
的explain
输出要复杂的多,mongo3.0版本对于explain
做了很大的调整,本文只讨论3.0以后版本的explain
情况。
包括count
, distinct
, group
, find
, findAndModify
, delete
,update
等操作均可以执行explain
。
explain
有三种执行模式:
queryPlanner Mode
:mongo
通过运行查询优化器选出winning plan
executionStats Mode
: 除了获取winning plan
,mongo
还会去真正的执行该plan
,然后返回执行时的一些统计信息;该模式比较耗时(注意:对于写操作,mongo
虽然会去执行这些winning plan
,但是不会将这些修改应用到该database
上)allPlansExecution Mode
:返回更多的信息,默认模式
shell环境下可以通过db.collection.explain()
、cursor.explain()
、db.runCommand()
三种方法来执行explain
,pymongo可以通过db.command
、cursor.explain()
来获取explain
的结果。
注意:aggrgate仅仅会在queryplanner模式下运行explain
explain结果分析
1 | { |
各字段的意义如下所示:
namespace
: 该query
所查询的表winningPlan
: 查询优化器针对该query
返回的最优执行计划详细内容stage
:非常重要的一个字段,后面分析inputStage
:stage
的child stage
,此处是IXSCAN,表示进行的是index scanning
keyPattern
: 所扫描的index
内容,此处是w:1
与n:1
indexName
: 所选用的index
isMultiKey
: 是否是Multikey
,此处返回是false,如果索引建立在array
上,此处将是truedirection
: 此query
的查询顺序,此处是forward
,如果用了.sort({w:-1})
将显示backward
indexBounds
:winningplan
所扫描的索引范围,此处查询条件是w:1
,使用的index
是w
与n
的联合索引,故w
是1.0
,1.0
而n
没有指定在查询条件中,故是MinKey
,MaxKey
rejectedPlans
:其他执行计划(非最优而被查询优化器reject的)的详细返回
如果在executionStats
模式或者allPlansExecution
模式下执行explain
,其结果中还会包含executionStats
信息:
1 | "executionStats" : { |
其中重要字段含义如下:
executionSuccess
:是否执行成功nReturned
:查询的返回条数executionTimeMillis
:整体执行时间totalKeysExamined
:索引扫描次数totalDocsExamined
:document
扫描次数
stage
作为explain
结果非常重要的一个字段,指明目前处于哪个阶段,常见的stage
有:COLLSCAN
(全表扫描), IXSCAN
(索引扫描), FETCH
(根据索引去检索指定document
), SHARD_MERGE
(将各个分片返回数据进行merge
), SOR
T(在内存中进行排序),LIMIT
(使用limit
限制返回数), SKIP
(使用skip
进行跳过), TEXT
(全文索引进行查询), PROJECTION
(限定返回字段), IDHACK
(针对_id
进行查询)等等
对于普通查询,我们最希望看到的组合有这些:
- Fetch+IDHACK
- Fetch+ixscan
- Limit+(Fetch+ixscan)
- PROJECTION+ixscan
- SHARDING_FILTER+ixscan等undefined不希望看到包含如下的stage:undefinedCOLLSCAN(全表扫),SORT(使用sort但是无index),不合理的SKIP,SUBPLA(未用到index的$or)
查询分析器
无论哪种模式,explain
的结果中都会有winning plan
的信息,这些winning plan
是通过mongo
查询分析器获得的,查询分析器会缓存winning plan
的信息,所以query planner
模式的explain
执行速度很快。
下面这幅图说明了查询分析器的执行逻辑:
详细信息见:Query Plans
参考文章: