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")