1、慢查询
开启:
use ntrailcenter
db.setProfilingLevel(1,1000)
关闭:
db.setProfilingLevel(0)
operationProfiling:
mode: slowOp
slowOpThresholdMs: 100
基于上述配置,MongoDB 会将超过 100ms 的请求记录到对应DB 的 system.profile 集合里,system.profile 默认是一个最多占用 1MB 空间的 capped collection。
查看最近3条 慢请求,{$natrual: -1} 代表按插入数序逆序
db.system.profile.find().sort({$natrual: -1}).limit(100)
情况1:全盘扫描
全集合(表)扫描 COLLSCAN,当一个查询(或更新、删除)请求需要全表扫描时,是非常耗CPU资源的,所以当你在 system.profile 集合 或者日志文件发现 COLLSCAN 关键字时,就得注意了,很可能就是这些查询吃掉了你的 CPU 资源;确认一下,如果这种请求比较频繁,最好是针对查询的字段建立索引来优化。
一个查询扫描了多少文档,可查看 system.profile 里的 docsExamined 的值,该值越大,请求CPU开销越大。关键字:COLLSCAN、 docsExamined。
情况2:索引未添加或不合理
一个走索引的查询,扫描了多少条索引,可查看 system.profile 里的 keysExamined 字段,该值越大,CPU 开销越大。关键字:IXSCAN、keysExamined。
情况3:大量数据排序
当查询请求里包含排序的时候,如果排序无法通过索引满足,MongoDB 会在内存里将结果进行排序,而排序这个动作本身是非常耗 CPU 资源的,优化的方法仍然是建立索引,对经常需要排序的字段,建立索引。当你在 system.profile 集合 或者 日志文件发现 SORT 关键字时,就可以考虑通过索引来优化排序。当请求包含排序阶段时, system.profile 里的 hasSortStage 字段会为 true。关键字:SORT、hasSortStage。
其他还有诸如建索引,aggregationv等操作也可能非常耗 CPU 资源,但本质上也是上述几种场景;建索引需要全表扫描,而vaggeregation 也是遍历、查询、更新、排序等动作的组合。
基本上就是以上几种情况,还有的话就是MongoDB确实已经达到瓶颈,此时可能需要通过shard来解决。
处理慢日志脚本:
with open('data','r+',encoding='utf8') as f:
# for data in str(f.readline()).replace('NumberLong\(','').replace('\)',''):
for data in f.readlines():
str_data = data.replace('NumberLong(','').replace(')','').replace('ISODate(','').replace('true','0').replace('false','1')
dict_data = eval(str_data)
print(dict_data['op'],dict_data['millis'],dict_data['ns'],dict_data['query'])