是否开启了慢查询记录
选择某一数据库,执行db.getProfilingStatus(),可得到如下结果:
was=1表示开启了慢查询记录,0表示未开启
showms表示记录超过多少ms的数据库操作
开启记录慢查询
开始方法有2种
选中某一数据库后,shell里执行db.setProfilingLevel(1,200),其中,参数1表示记录的级别,参数2表示记录大于多少ms的操作
0:关闭,不收集任何数据。1:收集慢查询数据,默认是100毫秒。2:收集所有数据
#也可以MongoDB启动时,开启Profilingmongod --profile=1 --slowms=200#或者在配置文件里添加profile = 1slowms = 200
分析方法
查看system.profile表,里面会记录所有慢查询记录
其中一条的详细说明如下:
#下面是一个超过200ms的查询语句{"op" : "query", #操作类型,有insert、query、update、remove、getmore、command"ns" : "F10data3.f10_2_8_3_jgcc","query" : { #具体的查询语句 包括过滤条件,limit行数 排序字段filter" : {"jzrq" : {"$gte" : ISODate("2017-03-31T16:00:00.000+0000"),"$lte" : ISODate("2017-06-30T15:59:59.000+0000")},"jglxfldm" : 10.0},"ntoreturn" : 200.0,"sort" : { #如果有排序 则显示排序的字段 这里是 RsId"RsId" : 1.0}},"keysExamined" : 0.0, #索引扫描数量 这里是全表扫描,没有用索引 所以是 0"docsExamined" : 69608.0, #浏览的文档数 这里是全表扫描 所以是整个collection中的全部文档数"numYield" : 546.0, #该操作为了使其他操作完成而放弃的次数。通常来说,当他们需要访问还没有完全读入内存中的数据时,操作将放弃。这使得在MongoDB为了放弃操作进行数据读取的同时,还有数据在内存中的其他操作可以完成。"locks" : { #锁信息,R:全局读锁;W:全局写锁;r:特定数据库的读锁;w:特定数据库的写锁"Global" : {"acquireCount" : {"r" : NumberLong(1094) #该操作获取一个全局级锁花费的时间。}},"Database" : {"acquireCount" : {"r" : NumberLong(547)}},"Collection" : {"acquireCount" : {"r" : NumberLong(547)}}},"nreturned" : 200.0, #返回的文档数量"responseLength" : 57695.0, #返回字节长度,如果这个数字很大,考虑值返回所需字段"millis" : 264.0, #消耗的时间(毫秒)"planSummary" : "COLLSCAN, COLLSCAN", #执行概览 从这里看来 是全表扫描"execStats" : { #详细的执行计划 这里先略过 后续可以用 explain来具体分析},"ts" : ISODate("2017-08-24T02:32:49.768+0000"), #命令执行的时间"client" : "10.3.131.96", #访问的ip或者主机"allUsers" : [],"user" : ""}
常见问题:
1. 如果发现 millis 值比较大,那么就需要作优化。2. 如果docsExamined数很大,或者接近记录总数(文档数),那么可能没有用到索引查询,而是全表扫描。3. 如果keysExamined数为0,也可能是没用索引。4. 结合 planSummary 中的显示,上例中是 "COLLSCAN, COLLSCAN" 确认是全表扫描5. 如果 keysExamined 值高于 nreturned 的值,说明数据库为了找到目标文档扫描了很多文档。这时可以考虑创建索引来提高效率。6. 索引的键值选择可以根据 query 中的输出参考,上例中 filter:包含了 jzrq和jglxfldm 并且按照RsId排序,所以 我们的索引索引可以这么建: db.f10_2_8_3_jgcc.ensureindex({jzrq:1,jglxfldm:1,RsId:1}
planSummary的其他类型可选项:
COLLSCAN #全表扫描 避免IXSCAN #索引扫描 可以改进 选用更高效的索引FETCH #根据索引去检索指定documentSHARD_MERGE #将各个分片返回数据进行merge 尽可能避免跨分片查询SORT #表明在内存中进行了排序(与老版本的scanAndOrder:true一致) 排序要有indexLIMIT #使用limit限制返回数 要有限制 Limit+(Fetch+ixscan)最优SKIP #使用skip进行跳过 避免不合理的skipIDHACK #针对_id进行查询 推荐,_id 默认主键,查询速度快SHARDING_FILTER #通过mongos对分片数据进行查询 SHARDING_FILTER+ixscan最优COUNT #利用db.coll.explain().count()之类进行count运算COUNTSCAN #count不使用Index进行count时的stage返回 避免 这种情况建议加索引COUNT_SCAN #count使用了Index进行count时的stage返回 推荐SUBPLA #未使用到索引的$or查询的stage返回 避免TEXT #使用全文索引进行查询时候的stage返回PROJECTION #限定返回字段时候stage的返回 选择需要的数据, 推荐PROJECTION+ixscan
本文介绍了如何开启和分析MongoDB的慢查询记录。通过检查was参数确认慢查询是否已开启,并说明了如何设置记录级别。同时,文章提到了通过观察system.profile表来查看慢查询详情,帮助用户定位和解决问题。
74

被折叠的 条评论
为什么被折叠?



