慢请求定位方法
在相同业务场景下,架构设计和库、集合、索引等设计会影响查询性能,良好的设计可以提高查询性能,反之会出现很多慢请求(执行时间很长的语句),这些慢请求会消耗很多的系统性能。
本文主要介绍导致慢请求的原因和解决方案。
排查思路
DDS支持在控制台上查看慢日志信息,针对慢日志中过长的操作需要从执行最慢的操作入手,逐个进行优化。
- 对于操作执行时长超过1s时,对应的操作可能会有问题,需要视具体情况分析。
- 对于操作执行时长超过10s时,则需要优化对应的操作。
若存在某个聚合操作,因其比较慢,此时操作执行时长超过10s的情况属于正常现象。
分析方法
- 连接数据库。
- 针对慢查询可以通过如下命令检查其执行计划。
explain()
例如:
db.test.find({"data_id" : "ae4b5769-896f-465c-9fbd-3fd2f3357637"}).explain(); db.test.find({"data_id" : "775f57c2-b63e-45d7-b581-3822dba231b4"}).explain("executionStats");
对于查询而言,因为覆盖查询不需要读取文档,而是直接从索引中返回结果,这样的查询非常高效,所以尽可能使用索引覆盖查询。如果explain()的输出显示indexOnly字段为真,则说明这个查询就被一个索引覆盖。
- 执行计划解析。
- 查看执行时间。
executionStats.executionStages.executionTimeMillisEstimate和executionStats.executionStages.inputStage. executionTimeMillisEstimate时间越短越好。
表1 参数说明 参数名称
描述
executionStats.executionTimeMillis
执行计划选择和执行的所有时间
executionStats.executionStages.executionTimeMillisEstimate
执行计划的执行完成时间
executionStats.executionStages.inputStage. executionTimeMillisEstimate
执行计划下的子阶段执行完成时间
- 查看扫描条数。
如表2中三个条目相同为最佳。
- 查看Stage状态。
- 查看执行时间。
优化方案
- 对于无索引覆盖的查询,则需要根据查询条件创建对应索引。
- 对于点查可以创建hash索引。
- 对于多字段查询,单字段重复度较高的场景,创建复合索引。
- 对于范围查找,结果集有序的查询,创建升序或者降序索引。
- 对于复合索引,由于复合索引是前缀排序查询,所以查询条件的顺序要与索引字段的顺序一致。
- 对于分区集合(表)、大集合(超过10万记录),不要直接对大数据量的表使用模糊查询(即不能使用like)。这样会造成查询扫描的记录过多,建议先基于索引字段查询,过滤出较小的数据集后再使用模糊查询。
- 避免使用$not。MongoDB 并不会对缺失的数据进行索引,因此$not的查询条件将会要求在一个结果集中扫描所有记录。如果$not是唯一的查询条件,会对集合进行全表扫描。
- 用$and时把匹配最少结果的条件放在最前面,用$or时把匹配最多结果的条件放在最前面。
- 检查实例规格的性能基线,分析当前的业务需求是否达到上限,如已达当前实例性能瓶颈,请及时提升实例规格。