mongo语句查询条件中出现null或空串,可能会导致索引失效,查询优化器无法选择正确的查询计划,出现慢查询引起服务异常
mongo查询的执行计划使用了LRU缓存,在很多种情况下会失效,导致重新选择执行计划并缓存,供后续同类查询直接使用;
服务开始时一直运行正常,当执行计划失效后,恰好出现null值的查询导致选择了错误的执行计划并缓存,后续正常的查询也会出现异常。
二、事件脉络 1、起因用户中心收到业务方反馈,第三方登录注册出现频繁dubbo调用超时。
2、排查处理a、查询用户中心cat监控,确认用户中心是否收到请求且正常响应。
当前状态:
正常状态:
对比结果:
用户中心已收到正常请求,排除客户端调用问题;
用户中心当前响应时间异常高出平常的响应时间,判断为用户中心内部业务处理出现问题。
b、查看kibana日志,发现无异常日志;
c、使用Arthas诊断工具,监控业务调用链各部分耗时情况;
定位原因为mongo查询慢导致整体业务处理超时。
d、分析mongo查询语句,查看索引情况
“userBindInfo.dfId”字段存在索引,查询语句也无明显异常。
e、查看华为云后台mongo慢日志
通过慢日志发现,mongo并未使用“userBindInfo.dfId”作为索引查询条件,而是使用了“app”作为索引查询条件。
初步认为索引匹配度不够,mongo没正确使用索引。
f、新增联合索引,提高索引匹配度,查询时间恢复正常,接口恢复正常。
3、问题分析a、explain()语句分析
发现mongo执行计划选择正确,这正好解释了服务在之前很长的一段时间内都是正常的原因;mongo慢日志中的执行计划却选择错误,表明有什么原因导致了mongo执行计划的选择发生了变更。b、文档查询
MongoDB 查询优化器会缓存最有效的查询计划,关联的计划缓存条目会用于具有相同查询形状的后续查询;计划缓存会出现刷新:MongoDB重启;索引或者集合的删除添加更新等操作;最近最少使用 (LRU) 缓存替换机制清除最近最少访问的缓存条目。结论:之前使用了计划缓存服务正常,到了某一时刻,计划缓存失效,MongoDB重新选择计划,此时选择了错误的计划并缓存,导致后续查询全部出现问题
c、查询首次出现的慢日志
发现查询条件中出现了null值,本地再次分析:
结果与线上表现一致
4、回顾紧急处理时,直接创建了一个新的索引,导致了计划缓存失效,重新选择计划并缓存,所以服务恢复了正常。
三、总结 避免空值的查询;尽可能的使用explain()分析各种不同的查询情况;可以使用mongo提供的PlanCache相关功能,查看计划缓存情况;可使用hint()推荐查询索引。到此这篇关于一次线上mongo慢查询问题排查处理的文章就介绍到这了,更多相关mongo慢查询问题排查内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!