MongoDB使用profile分析慢查詢的步驟
在MongoDB中,如果發(fā)生了慢查詢,我們?nèi)绾蔚玫竭@些慢查詢的語句,并優(yōu)化呢?今天來看這塊兒的一些心得。
01 如何收集慢查詢?
在MongoDB中,通常可以開啟profile來收集慢日志,查看當(dāng)前profile狀態(tài)的語句如下:
test1:PRIMARY>db.getProfilingStatus()
{
"was":2,
"slowms":0,
"sampleRate":1,
"$gleStats":{
"lastOpTime":Timestamp(0,0),
"electionId":ObjectId("7fffffff0000000000000005")
},
"lastCommittedOpTime":Timestamp(1619186976,2),
"$configServerState":{
"opTime":{
"ts":Timestamp(1619186976,1),
"t":NumberLong(2)
}
},
"$clusterTime":{
"clusterTime":Timestamp(1619186976,2),
"signature":{
"hash":BinData(0,"zvwFpgc0KFxieMpj7mBPdrOnonI="),
"keyId":NumberLong("6904838687771590657")
}
},
"operationTime":Timestamp(1619186976,2)
}
這里我們可以看到2個(gè)關(guān)鍵參數(shù),分別是was和slowms,其中:
was=0,代表不記錄任何的語句;
was=1,代表記錄執(zhí)行時(shí)間超過slowms的語句
was=2,代表記錄所有的語句
slowms代表語句的閾值,單位是ms
上圖中的結(jié)果代表我們的實(shí)例會(huì)收集所有的查詢語句。profile收集的查詢語句結(jié)果存放在admin數(shù)據(jù)庫中的system.profile集合中,可以通過下面的方法進(jìn)行訪問:
test1:PRIMARY>useadmin
switchedtodbadmin
test1:PRIMARY>db.system.profile.find({'op':'query'},{'op':1,'ns':1,'millis':1,'ts':1})
{"op":"query","ns":"admin.system.users","millis":0,"ts":ISODate("2020-08-27T07:22:14.815Z")}
{"op":"query","ns":"admin.system.users","millis":0,"ts":ISODate("2020-08-27T07:22:15.139Z")}
{"op":"query","ns":"admin.system.users","millis":0,"ts":ISODate("2020-08-27T07:22:15.141Z")}
{"op":"query","ns":"admin.system.users","millis":0,"ts":ISODate("2020-08-27T07:22:15.239Z")}
{"op":"query","ns":"admin.system.version","millis":0,"ts":ISODate("2020-08-27T07:22:16.155Z")}
{"op":"query","ns":"admin.system.version","millis":0,"ts":ISODate("2020-08-27T07:22:16.192Z")}
{"op":"query","ns":"admin.system.users","millis":0,"ts":ISODate("2020-08-27T07:22:16.225Z")}
{"op":"query","ns":"admin.system.users","millis":0,"ts":ISODate("2020-08-27T07:22:16.273Z")}
{"op":"query","ns":"admin.system.version","millis":0,"ts":ISODate("2020-08-27T07:22:16.276Z")}
02 system.profile慢查詢集合分析
admin數(shù)據(jù)庫中的system.profile是一個(gè)固定集合,保存著超過設(shè)置的慢查詢的結(jié)果。我們來看里面的一條慢查詢。
利用下面的方法,來拿到一條數(shù)據(jù),并對其中的關(guān)鍵字段進(jìn)行注釋說明:
test1:PRIMARY>db.system.profile.findOne({'op':'query'})
{
"op":"query",#操作類型
"ns":"admin.system.users",#命名空間
"command":{
"find":"system.users",
"filter":{
"_id":"admin.root"#過濾的字段
},
"limit":1,
"singleBatch":true,
"lsid":{
"id":UUID("a6034f5e-77c1-4b19-9669-60e1253edf4b")
},
"$readPreference":{
"mode":"secondaryPreferred"
},
"$db":"admin"
},
"keysExamined":1,#掃描的索引數(shù)
"docsExamined":1,#掃描的行數(shù)
"cursorExhausted":true,
"numYield":0,
"nreturned":1,#返回的值的行數(shù)
"locks":{
xxxx#鎖信息
},
"flowControl":{
},
"storage":{
},
"responseLength":647,
"protocol":"op_query",
"millis":0,#這個(gè)查詢的執(zhí)行時(shí)間,因?yàn)槲覀冊O(shè)置的profilestatus是0,因此所有操作都被記錄了。
"planSummary":"IDHACK",#針對_id進(jìn)行查詢
"execStats":{#查詢執(zhí)行狀態(tài)
"stage":"IDHACK",
"nReturned":1,
"executionTimeMillisEstimate":0,
"works":2,
"advanced":1,
"needTime":0,
"needYield":0,
"saveState":0,
"restoreState":0,
"isEOF":1,
"keysExamined":1,
"docsExamined":1
},
"ts":ISODate("2020-08-27T07:22:14.815Z"),
"clie
03 慢查詢分析利器---explain
通常情況下,我們可以使用MongoDB的explain語法來分析一個(gè)語句的查詢性能,包含是否用到索引、掃描行數(shù)等信息,explain語法的基本用法:
后置寫法
db.system.profile.find({'op':'query'}).explain()
前置寫法
db.system.profile.explain().find({'op':'query'})
其中,explain可以放在查詢語句的后面或者前面,當(dāng)然find語法也可以是update、remove、insert
explain語法的輸出分為3種不同的詳細(xì)程度,分別如下:
三種清晰度模式,清晰度越高,則輸出的信息越全,默認(rèn)情況下是queryPlanner:
1、queryPlanner模式(默認(rèn))
db.products.explain().count({quantity:{$gt:50}})2、executionStats模式
db.products.explain("executionStats").count({quantity:{$gt:50}})3、allPlansExecution模式
db.products.explain("allPlansExecution").count({quantity:{$gt:50}})
其中,allPlansExecution模式輸出的信息最多。
下面是一個(gè)explain語法的輸出內(nèi)容,查詢的SQL如下:
db.getCollection('files').find(
{"cTime":{
"$gte":ISODate("2021-04-18"),
"$lt":ISODate("2021-04-19")
}}).limit(1000).explain("allPlansExecution")
輸出的結(jié)果如下:
{
"queryPlanner":{ # 代表查詢的執(zhí)行計(jì)劃
"plannerVersion":1, # 版本號
"namespace":"fs.files", # 查詢的命名空間,也就是集合名稱
"indexFilterSet":false, # 是否使用了索引過濾,注意,它并不能判定是否使用了索引
"parsedQuery":{ # 查詢語法解析樹
"$and":[
{
"cTime":{
"$lt":ISODate("2021-04-19T00:00:00Z")
}
},
{
"cTime":{
"$gte":ISODate("2021-04-18T00:00:00Z")
}
}
]
},
"winningPlan":{ # 最終選擇的查詢計(jì)劃
"stage":"LIMIT", # 查詢的階段,很重要,下面詳細(xì)介紹
"limitAmou
首先解釋下stage的幾個(gè)階段:
- COLLSCAN---全表掃描
- IXSCAN---索引掃描
- FETCH---根據(jù)索引去檢索文檔
- SHARD_MERGE---合并分片結(jié)果
- IDHACK---針對id進(jìn)行查詢
- LIMIT---執(zhí)行l(wèi)imit
了解了這些stage的階段之后,我們可以看到,一個(gè)查詢的過程是一層一層解析的,所以可以看到,stage這個(gè)字段有嵌套的情況。winningPlan中的執(zhí)行計(jì)劃也是按照一層一層的順序去執(zhí)行:
1、先執(zhí)行最內(nèi)層的索引掃描(IXSCAN);
2、再執(zhí)行外面的FETCH,根據(jù)索引去拿文檔
3、執(zhí)行最后一步的limit,取指定數(shù)目個(gè)結(jié)果返回給客戶端
以上就是MongoDB profile分析慢查詢的示例的詳細(xì)內(nèi)容,更多關(guān)于MongoDB profile分析慢查詢的資料請關(guān)注本站其它相關(guān)文章!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。
關(guān)注官方微信