4.8 小技巧——使用explain命令验证优化
前面说过,建立索引的目的是用来加速数据查询的。那么,如何判断索引是否合理,或者说怎样评估索引所起到的作用呢?
是否存在这么一个工具,可以提前告知我们一些预期的效果呢?答案是肯定的。MongoDB提供了explain命令,它可以帮助我们评估指定查询模型(query model)的计划。
通常,我们需要关心的问题如下:
● 查询是否使用了索引。
● 索引是否减少了扫描的记录数量。
● 是否存在低效的内存排序。
● ……
接下来,继续使用之前创建的book集合,在没有任何索引的情况下尝试评估查询计划,代码如下:
返回的信息量有点多,但务必记住一点,现在的集合没有创建任何索引(除了自动创建的_id索引),所以查询计划显得有些糟糕:
● winningPlan表示获胜的计划,即数据库经过一系列评估后选择的最优计划,stage=COLLSCAN则说明这是一个全表扫描。
● executionStats描述了执行的过程信息,其中,nReturned=1是指返回了一条结果,而totalDocsExamined=50说明整个过程扫描了50条记录。
尽管集合中的数据量并不大,但至少可以看出在没有索引的情况下查询会多么低效。为了返回1个文档需要耗费50次的扫描,假设集合有1000万个文档,那么就需要扫描5亿次!
为了优化这个查询,我们为标题建立一个升序索引,代码如下:
继续评估查询计划,代码如下:
这次的结果明显有些不同,相比第一次查询计划,其优化如下:
● 不再使用全表扫描(COLLSCAN)方式,取而代之的是索引扫描(IXSCAN)。
● totalDocsExamined=1,意味着扫描的文档数量只有1个。同时由于使用了索引扫描,因此可以看到totalKeysExamined=1。
executionStats.executionTimeMillis这个属性描述了执行过程所消耗的时间,一般需要配合一定的数据规模才能看出差异。
本例所提供的数据量太小,因此表现出来的执行时间并没有什么不同。但通过explain结果中的查询计划、命中比率(返回数/扫描数),却能明显地看到索引对于查询效率带来的提升。