问题描述
在使用文档数据库 MongoDB 的时发现 CPU使用率很高,从业务角度来看,发现数据读写处理缓慢,我该如何排查此类问题?
问题分析
通常来说,导致 MongoDB CPU 使用率高有如下几点原因:
- 查询语句不够优化,没有合理的索引。
- 请求并发量大,当前业务负载和实例类型不匹配,即超出当前服务能力。
- 有过重的计算任务。
解决方案
1. 查看当前正在运行的语句
与 MySQL 中 show full processlist
语句功能类似,在 MongoDB 中我们使用 db.currentOp()
来查看当前数据库正在运行的语句。
db.currentOp() 命令回显较多,我们需要重点关注如下字段:
- client 发起请求的客户端地址。
- opid 识别当前操作的标识符。
- secs_running 当前操作已经执行的时间,单位为秒。
- microsecs_running 当前操作已经执行的时间,单位为微秒。
- ns 当前操作的目标集合。
- op 当前操作的类型
- locks 跟锁相关的信息
关于 db.currentOp()
命令的更多用法,您可以参考文档[1]。
2. 分析慢日志
默认情况下,MongoDB 会将运行时间大于 100ms 的语句记录到慢日志中。通过分析慢日志,我们可以找到导致 CPU 升高的原因,可能有如下几种比较重要的情况:
- COLLSCAN:这意味着您的语句正在执行全表扫描,这是非常耗时的操作
- docsExamined:一个查询扫描了多少文档,该值越大,请求CPU开销越大
- IXSCAN & keysExamined:有时我们会发现即使查询走了索引,但是依旧运行缓慢,可能是由于索引创建的并不合理。
- SORT & hasSortStage:当查询需要进行排序时,如果无法利用索引,那么会在内存中进行排序,这也是非常耗时的操作。
3. 分析执行计划
MongoDB 提供了 explain()
方法来展示一个查询是如何执行的,分析执行计划是进行调优必不可少的环节。执行计划包括如下信息:
- 那些索引会被使用
- 查询语句是否能被索引覆盖来避免回表
- 所扫描的索引项数量
- 所返回的以及读取的文档数量
- 执行查询需要花费的时间
- ……
4. 使用与业务负载相符的实例类型
这里需要对业务以及整个 MongoDB 集群进行评估,如果发现当前集群的服务能力和业务增长不匹配时,您可能需要考虑提高整个集群的配置。
参考文档
[1] https://www.mongodb.com/docs/manual/reference/method/db.currentOp/ 如果您有其他问题,欢迎您联系火山引擎技术支持服务