NoSQL学习——文档数据库MongoDB(四)执行与性能检测
# 性能检测
MongoDB提供了针对查询和聚合的性能检测。在Mongo执行语句中,通过Explain方法进行检测,主要有在查询方法前或后两种方式,如db.users.find(...).explain()
或db.users.explain().find()
。使用explain后,执行的命令不会返回数据,而是返回一个包含执行情况解释的object,可能包括的域有queryPlanner和executionStats。
explain()
方法可以使用字符串参数指示返回的解释程度:
- 无参数:仅提供查询计划,即只包含都各阶段的解释,不提供实际执行的统计;
- "executionStats":展示计划和实际执行的计划的执行统计;
- "allPlansExecution":展示所有可能的查询计划的部分执行统计。
# 查询的执行过程
理论上,查询的优化可能与索引、文档数量、筛选条件的执行顺序等因素有关。通过更早地使用合适的索引过滤剩余文档,查询能够得到加速。在执行过程中,通过explain()
可以观察到索引的使用情况。在建立了多个索引的collection上执行查询时,MongoDB会根据索引的使用情况和执行顺序生成一组可以执行的计划,并通过部分运行之后的结果判断使用哪一个计划,并使其成为Winning Plan,其他的则被认为是Rejected Plan,在最终的查询中不予执行。
在执行解释中,一个Plan会包含多个阶段,类似于通过聚合指定的阶段。按阶段进行执行后,每阶段会有一个该阶段的执行方法解释。在解释中,不仅有该阶段返回的文档数量,还有是否使用了索引等,例如IXSCAN表示通过索引进行查询,否则就只能通过全表扫描FullTableScan进行查询,后者的时间复杂度显著高于前者。除此之外,在需要使用内存记录额外生成的查询结果的$group
和$sort
阶段,执行解释还会给出使用的内存大小。
结合这些信息,我们可以定向优化查询。例如,在发现了进行全表查询的阶段后,我们可以对所使用的字段建立索引用以加速;或者,通过比较不同的执行计划,优化文档筛选过程。
在explain()
的结果中,我们可以看到一些聚合的阶段会被整合得与我们编写的语句有所不同,其中有两个典型——$group
和project
会被整合为一个阶段,$sort
和$limit
会被整合为一个阶段。这样做的好处是,一个阶段的执行能够减少内存中相同文档的复制;另外,通过快速排序等手段结合limit,能通过使用更少的内存和读写操作完成输出。
# 总结
在这一章中,我们简单探索了MongoDB的性能检测和可能的优化方法。我们将在下一章中了解MongoDB集群的分片、复制和集群上读写的机制。