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