mongodb 慢查询排查
来源:
https://www.cnblogs.com/yangxiaoyi/p/7504753.html
https://www.cnblogs.com/luo-mao/p/6278170.html
http://www.pianshen.com/article/134476742/
开启慢日志
1.查看mongodb慢日志是否开起
use BJ_Rack;
db.getProfilingStatus();
发现没有开户慢日志
2.开启慢日志,设置超过100毫秒的操作为慢操作
db.setProfilingLevel(1,100);
3.查看慢日志内容
db.system.profile.find().sort({$natural:-1})
得到50个比较慢的操作日志.
通过配置文件开启:
operationProfiling:
mode: slowOp
slowOpThresholdMs: 100
查看当前操作
db.currentOp(true);
主要有以下信息:
- client – 请求是由哪个客户端发起的
- opid – 操作的opid,有需要的话,可以通过 db.killOp(opid) 杀死操作
- secs_running/microsecs_running – 请求运行的时间,如果这个值特别大就非常值得注意
- query/ns: 对集合进行的具体操作
- lock*:锁相关参数
慢请求分析 – 全表扫描 COLLSCAN
如果在日志中看到关键字 COLLSCAN,说明该查询在进行全表扫描,通常这就是 CPU 异常飙高的主要原因。
4.1. 查看扫描文档数
system.profile 里 docsExamined 的值显示了本次查询的扫描文档数。
4.2. 解决办法 – 添加索引
最好针对查询语句建立索引:
db.col.createIndex({"title":1})
- 1
我们也可以在添加索引时增加传入可选参数,例如,在生产环境我们通常不希望索引添加的操作阻塞其他数据库操作,这时就需要务必添加 background 参数:
db.col.createIndex({"title":1}, {'background', true})
- 1
5. 慢请求分析 – 索引设置不合理
有的时候,请求即使查询走了索引,执行也很慢,通常是因为索引建立不太合理或者匹配结果太多。
索引通常应该建立在区分度大的字段上。
在 system.profile 中,可以通过 keysExamined 字段查看查询扫描了多少条索引,如果该值过大,要考虑建立新的索引或优化查询了。
6. 慢请求分析 – 大量数据排序
当查询请求里包含排序的时候,如果排序无法通过索引满足,MongoDB 会在内存中对结果进行排序。
大家都知道,排序是非常消耗 CPU 的一项操作,最好在需要排序的字段上建立索引。
system.profile 中的 SORT 关键字反映了查询需要排序。
7. 服务能力评估
有时 CPU 消耗过高仅仅是单纯的因为服务器达到了上限。
如果上面的措施都无法让 CPU 占用率下降到合理的指标内,就要考虑扩容、升级来提升服务能力的上限。
但切忌将这个方法作为首要考虑的解决方案,合理的设置索引,建立资源预警,而不是盲目提升配置或在业务已经达到上限时再考虑优化。
8. 参考资料
https://docs.mongodb.com/manual/reference/method/db.currentOp/
https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/
https://docs.mongodb.com/manual/reference/database-profiler/
https://docs.mongodb.com/v3.2/reference/method/db.collection.createIndex/index.html
https://docs.mongodb.com/v3.2/indexes/index.html
https://docs.mongodb.com/v3.2/tutorial/analyze-query-plan/
https://yq.aliyun.com/articles/73389
http://www.runoob.com/mongodb/mongodb-indexing.html