MongoDB查詢優化-MongoDB Profiler
MongoDB Profiler 概述
官方文檔:https://docs.mongodb.com/manual/tutorial/manage-the-database-profiler/index.html
熟悉 Mysql
的人應該知道,Mysql
是有個慢查詢日志的,它可以幫助我們進行優化我們的 sql
,並提高我們系統的穩定性和流暢性。那么 MongoDB
中是否也有類似的功能嗎? 是有的,它就是 Database Profiler
(下面我直接稱為慢查詢了),我們可以通過設置 Database Profiler
來記錄一些超過閾值的查詢。然后我們后期可以通過這些記錄進行優化查詢。
MongoDB
的 慢查詢記錄儲存在 system.profile
里,默認情況下是關閉的,我們可以在數據庫級別上或者是節點級別上配置。
狀態碼 | 描述 |
---|---|
0 | 關閉慢查詢,默認情況下 |
1 | 超過閾值的查詢收集 |
2 | 為所有數據庫開啟慢查詢記錄,收集所有的數據 |
通過 MongoDB shell 啟用
# 為所有數據庫開啟慢查詢記錄
db.setProfilingLevel(2)
# 指定數據庫,並指定閾值慢查詢 ,超過20毫秒的查詢被記錄
use test
db.setProfilingLevel(1, { slowms: 20 })
# 隨機采集慢查詢的百分比值,sampleRate 值默認為1,表示都采集,0.42 表示采集42%的內容。
db.setProfilingLevel(1, { sampleRate: 0.42 })
# 查詢慢查詢級別和其它信息
db.getProfilingStatus()
# 僅返回慢查詢級別
db.getProfilingLevel()
# 禁用慢查詢
db.setProfilingLevel(0)
通過配置文件啟用
在ini
配置文件 mongodb.conf
添加以下參數, profile
參數是設置開啟等級,slowms
是設置閾值
profile = 1
slowms = 300
在 YAML
配置 文件配置
operationProfiling:
mode: <string> # 默認為 off,可選值 off、slowOp(對應上面的等級 1)、all(對應上面的等級 2)
slowOpThresholdMs: <int> # 閾值,默認值為100,單位毫秒
slowOpSampleRate: <double> # 隨機采集慢查詢的百分比值,sampleRate 值默認為1,表示都采集,0.42 表示采集42%的內容
常用命令和示例
# 查詢最近的10個慢查詢日志
db.system.profile.find().limit(10).sort( { ts : -1 } ).pretty()
# 查詢除命令類型為 ‘command’ 的日志
db.system.profile.find( { op: { $ne : 'command' } } ).pretty()
# 查詢數據庫為 mydb 集合為 test 的 日志
db.system.profile.find( { ns : 'mydb.test' } ).pretty()
# 查詢 低於 5毫秒的日志
db.system.profile.find( { millis : { $gt : 5 } } ).pretty()
# 查詢時間從 2012-12-09 3點整到 2012-12-09 3點40分之間的日志
db.system.profile.find({
ts : {
$gt: new ISODate("2012-12-09T03:00:00Z"),
$lt: new ISODate("2012-12-09T03:40:00Z")
}
}).pretty()
MongoDB慢日志解析
官方文檔:https://docs.mongodb.com/manual/reference/database-profiler/index.html
{
"op" : "query", # 操作類型,值可為command、count、distinct、geoNear、getMore、group、insert、mapReduce、query、remove、update
"ns" : "test.report", # 操作的數據庫和集合
"command" : { # 命令
"find" : "report", # 操作的集合
"filter" : { "a" : { "$lte" : 500 } }, # 查詢條件
"lsid" : {
"id" : UUID("5ccd5b81-b023-41f3-8959-bf99ed696ce9") #用戶的會話id
},
"$db" : "test" # 操作的數據庫
},
"cursorid" : 33629063128, # query和getmore 的游標id
"keysExamined" : 101, # MongoDB為執行操作而掃描的索引鍵的數量
"docsExamined" : 101, # MongoDB為了執行操作而掃描的集合中的文檔數。
"numYield" : 2, # 讓步次數,操作時讓其他的操作完成的次數。
"nreturned" : 101, # 操作返回的文檔數
"queryHash" : "811451DD", # 查詢的hash值
"planCacheKey" : "759981BA",
"locks" : { # 操作期間的鎖和所的類型
"Global" : { #表示全局鎖定
"acquireCount" : { #鎖定的次數
"r" : NumberLong(3) # 表示共享鎖
}
},
"Database" : { # 數據庫鎖
"acquireCount" : { "r" : NumberLong(1) },
"acquireWaitCount" : { "r" : NumberLong(1) },
"timeAcquiringMicros" : { "r" : NumberLong(69130694) }
},
"Collection" : { # 集合鎖
"acquireCount" : { "r" : NumberLong(1) }
}
},
"storage" : { # 儲存
"data" : {
"bytesRead" : NumberLong(14736), #操作 從磁盤放到緩存的數據的字節數
"timeReadingMicros" : NumberLong(17) # 操作 花費在磁盤讀取的時間,以微妙為單位
}
},
"responseLength" : 1305014, # 操作返回結果的文檔長度,單位為字節
"protocol" : "op_msg", # 消息的協議
"millis" : 69132, # 從 MongoDB 操作開始到結束耗費的時間
"planSummary" : "IXSCAN { a: 1, _id: -1 }", # 摘要
"execStats" : { # 操作執行過程中的詳細信息
"stage" : "FETCH", # 操作形式 ,COLLSCAN 用於集合掃描,IXSCAN 用於掃描索引鍵,FETCH 用於檢索文檔
"nReturned" : 101, # 返回的文檔數量
"executionTimeMillisEstimate" : 0,
"works" : 101,
"advanced" : 101,
"needTime" : 0,
"needYield" : 0,
"saveState" : 3,
"restoreState" : 2,
"isEOF" : 0,
"invalidates" : 0,
"docsExamined" : 101,
"alreadyHasObj" : 0,
"inputStage" : {
...
}
},
"ts" : ISODate("2019-01-14T16:57:33.450Z"), #操作的時間戳
"client" : "127.0.0.1", # 客戶端的ip
"appName" : "MongoDB Shell", #客戶端應用標識符
"allUsers" : [
{
"user" : "someuser", # 用戶
"db" : "admin" # 驗證的數據庫
}
],
"user" : "someuser@admin" # 經過驗證的用戶
}