mongodb慢查询排查

是否开启了慢查询记录

选择某一数据库,执行db.getProfilingStatus(),可得到如下结果:

was=1表示开启了慢查询记录,0表示未开启
showms表示记录超过多少ms的数据库操作


开启记录慢查询

开始方法有2种

只开启某一个数据库

选中某一数据库后,shell里执行db.setProfilingLevel(1,200),其中,参数1表示记录的级别,参数2表示记录大于多少ms的操作

 
  1. 0:关闭,不收集任何数据。
  2. 1:收集慢查询数据,默认是100毫秒。
  3. 2:收集所有数据

服务器上的所有数据库都开启

 
  1. #也可以MongoDB启动时,开启Profiling
  2. mongod --profile=1 --slowms=200
  3. #或者在配置文件里添加
  4. profile = 1
  5. slowms = 200

分析方法

查看system.profile表,里面会记录所有慢查询记录

其中一条的详细说明如下:

 
  1. #下面是一个超过200ms的查询语句
  2. {
  3. "op" : "query", #操作类型,有insert、query、update、remove、getmore、command
  4. "ns" : "F10data3.f10_2_8_3_jgcc",
  5. "query" : { #具体的查询语句 包括过滤条件,limit行数 排序字段
  6. filter" : {
  7. "jzrq" : {
  8. "$gte" : ISODate("2017-03-31T16:00:00.000+0000"),
  9. "$lte" : ISODate("2017-06-30T15:59:59.000+0000")
  10. },
  11. "jglxfldm" : 10.0
  12. },
  13. "ntoreturn" : 200.0,
  14. "sort" : { #如果有排序 则显示排序的字段 这里是 RsId
  15. "RsId" : 1.0
  16. }
  17. },
  18. "keysExamined" : 0.0, #索引扫描数量 这里是全表扫描,没有用索引 所以是 0
  19. "docsExamined" : 69608.0, #浏览的文档数 这里是全表扫描 所以是整个collection中的全部文档数
  20. "numYield" : 546.0, #该操作为了使其他操作完成而放弃的次数。通常来说,当他们需要访问
  21. 还没有完全读入内存中的数据时,操作将放弃。这使得在MongoDB为了
  22. 放弃操作进行数据读取的同时,还有数据在内存中的其他操作可以完成。
  23. "locks" : { #锁信息,R:全局读锁;W:全局写锁;r:特定数据库的读锁;w:特定数据库的写锁
  24. "Global" : {
  25. "acquireCount" : {
  26. "r" : NumberLong(1094) #该操作获取一个全局级锁花费的时间。
  27. }
  28. },
  29. "Database" : {
  30. "acquireCount" : {
  31. "r" : NumberLong(547)
  32. }
  33. },
  34. "Collection" : {
  35. "acquireCount" : {
  36. "r" : NumberLong(547)
  37. }
  38. }
  39. },
  40. "nreturned" : 200.0, #返回的文档数量
  41. "responseLength" : 57695.0, #返回字节长度,如果这个数字很大,考虑值返回所需字段
  42. "millis" : 264.0, #消耗的时间(毫秒)
  43. "planSummary" : "COLLSCAN, COLLSCAN", #执行概览 从这里看来 是全表扫描
  44. "execStats" : { #详细的执行计划 这里先略过 后续可以用 explain来具体分析
  45. },
  46. "ts" : ISODate("2017-08-24T02:32:49.768+0000"), #命令执行的时间
  47. "client" : "10.3.131.96", #访问的ip或者主机
  48. "allUsers" : [
  49. ],
  50. "user" : ""
  51. }

常见问题:

 
  1. 1. 如果发现 millis 值比较大,那么就需要作优化。
  2. 2. 如果docsExamined数很大,或者接近记录总数(文档数),那么可能没有用到索引查询,而是全表扫描。
  3. 3. 如果keysExamined数为0,也可能是没用索引。
  4. 4. 结合 planSummary 中的显示,上例中是 "COLLSCAN, COLLSCAN" 确认是全表扫描
  5. 5. 如果 keysExamined 值高于 nreturned 的值,说明数据库为了找到目标文档扫描了很多文档。这时可以考虑创建索引来提高效率。
  6. 6. 索引的键值选择可以根据 query 中的输出参考,上例中 filter:包含了 jzrqjglxfldm 并且按照RsId排序,所以 我们的索引
  7. 索引可以这么建: db.f10_2_8_3_jgcc.ensureindex({jzrq:1,jglxfldm:1,RsId:1}

planSummary的其他类型可选项:

 
  1. COLLSCAN #全表扫描 避免
  2. IXSCAN #索引扫描 可以改进 选用更高效的索引
  3. FETCH #根据索引去检索指定document
  4. SHARD_MERGE #将各个分片返回数据进行merge 尽可能避免跨分片查询
  5. SORT #表明在内存中进行了排序(与老版本的scanAndOrder:true一致) 排序要有index
  6. LIMIT #使用limit限制返回数 要有限制 Limit+(Fetch+ixscan)最优
  7. SKIP #使用skip进行跳过 避免不合理的skip
  8. IDHACK #针对_id进行查询 推荐,_id 默认主键,查询速度快
  9. SHARDING_FILTER #通过mongos对分片数据进行查询 SHARDING_FILTER+ixscan最优
  10. COUNT #利用db.coll.explain().count()之类进行count运算
  11. COUNTSCAN #count不使用Index进行count时的stage返回 避免 这种情况建议加索引
  12. COUNT_SCAN #count使用了Index进行count时的stage返回 推荐
  13. SUBPLA #未使用到索引的$or查询的stage返回 避免
  14. TEXT #使用全文索引进行查询时候的stage返回
  15. PROJECTION #限定返回字段时候stage的返回 选择需要的数据, 推荐PROJECTION+ixscan

 

你可能感兴趣的:(mongodb慢查询排查)