MongoDB profiler是一個很好的工具,可以幫助在數據庫運行的時候分析慢查詢。默認情況下,慢查詢指的是查詢時間在100ms以上。這個值是可以修改的。
先看一下怎麼用。
step 1 登錄到primary server
假定有一個MongoDB Replica-set集群,用mongo shell登錄到primary server上。
step 2 設置profile level
db.setProfilingLevel(1)
現在MongoDB server會運行的較慢,會將發現的慢查詢語句寫到db.system.profile集合中。下面演示了查找最近一條慢查詢的方法
rs1:PRIMARY> db.system.profile.find().limit(1).sort( { ts : -1 } ).pretty() { "op" : "query", "ns" : "kaimei.digital_message", "query" : { "query" : { "display_id" : { "$in" : [ ObjectId("52312efca9bb51d66fa724a8"), ObjectId("52312efca9bb51d66fa724ab"), ObjectId("52312efca9bb51d66fa724ac"), ObjectId("52312efca9bb51d66fa724ae"), ObjectId("5252c23133f6792263dd1cfe"), ObjectId("5271ab5033f6792263dd8cfc"), ...... ObjectId("527710eb33f6792263ddba43"), ObjectId("527710eb33f6792263ddba44") ] }, "status" : { "$nin" : [ "success", "deprecated" ] } }, "orderby" : { "_id" : 1 } }, "ntoreturn" : 0, "ntoskip" : 0, "nscanned" : 210342, "keyUpdates" : 0, "numYield" : 454, "lockStats" : { "timeLockedMicros" : { "r" : NumberLong(1755835), "w" : NumberLong(0) }, "timeAcquiringMicros" : { "r" : NumberLong(1145626), "w" : NumberLong(1599) } }, "nreturned" : 0, "responseLength" : 20, "millis" : 1147, "ts" : ISODate("2013-12-10T13:08:05.839Z"), "client" : "192.168.1.58", "allUsers" : [ ], "user" : "" } step 4 建立索引優化查詢
現在看看有什麼方法能夠優化,通過getIndexes發現display_id和status沒有建立索引。因此創建索引
rs1:PRIMARY> db.digital_message.ensureIndex({display_id: 1, status: 1}, {background: true} ) rs1:PRIMARY> db.digital_message.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "kaimei.digital_message", "name" : "_id_" }, { "v" : 1, "key" : { "display_id" : 1, "status" : 1 }, "ns" : "kaimei.digital_message", "name" : "display_id_1_status_1", "background" : true } ]
background: true很重要,可以保證建立索引過程中數據庫仍然可以處理請求。這裡我建立的是雙字段的組合索引。
現在再試一下:
] }, "status" : { "$nin" : [ "success", "deprecated" ] } }, "updateobj" : { "$set" : { "status" : "sending" } }, "nscanned" : 37693, "nupdated" : 0, "keyUpdates" : 0, "numYield" : 3, "lockStats" : { "timeLockedMicros" : { "r" : NumberLong(0), "w" : NumberLong(248113) }, "timeAcquiringMicros" : { "r" : NumberLong(0), "w" : NumberLong(114619) } }, "millis" : 149, "ts" : ISODate("2013-12-10T13:30:46.400Z"), "client" : "192.168.1.55", "allUsers" : [ ], "user" : "" }可以看到速度提升了很多。由於我的in查詢至少涉及到1500行以上記錄的記錄,所以這個149 ms的查詢時間是可以接受的。
以後再打開profile時,可以修改慢查詢的衡量標准,比如下面就改成了200 ms以上的才算慢查詢。
db.setProfilingLevel(1, 200)
step 5 清空profile集合,還原到最初。
db.setProfilingLevel(0)db.system.profile.drop()db.createCollection("system.profile")