使用文檔數(shu)據庫服務(wu)時(shi),如果您的CPU使用率達到80%,則認為CPU存在瓶(ping)頸。此時(shi),會(hui)導(dao)致數(shu)據讀寫處理緩(huan)慢,從(cong)而影響業務(wu)正常運行。
本章節幫助您分(fen)析數(shu)據(ju)庫(ku)正在執(zhi)行的(de)(de)請(qing)(qing)求(qiu)和數(shu)據(ju)庫(ku)慢請(qing)(qing)求(qiu),經過分(fen)析優(you)化后,使得數(shu)據(ju)庫(ku)的(de)(de)查詢相對合理,所有的(de)(de)請(qing)(qing)求(qiu)都高(gao)(gao)效使用了(le)索引,從而排查文檔數(shu)據(ju)庫(ku)服務CPU使用率(lv)高(gao)(gao)的(de)(de)問題。
分析DDS數據庫正在執行的請求
- 通過Mongo Shell連接DDS實例。
開(kai)通公網(wang)訪問(wen)的實例,具體請參見:
未開通(tong)公網訪問(wen)的(de)實例,具體請參見:
- 執行以下命令,查看數據庫當前正在執行的操作。
db.currentOp()
回顯如下:
{
"raw" : {
"shard0001" : {
"inprog" : [
{
"desc" : "StatisticsCollector",
"threadId" : "140323686905600",
"active" : true,
"opid" : 9037713,
"op" : "none",
"ns" : "",
"query" : {
},
"numYields" : 0,
"locks" : {
},
"waitingForLock" : false,
"lockStats" : {
}
},
{
"desc" : "conn2607",
"threadId" : "140323415066368",
"connectionId" : 2607,
"client" : "172.16.36.87:37804",
"appName" : "MongoDB Shell",
"active" : true,
"opid" : 9039588,
"secs_running" : 0,
"microsecs_running" : NumberLong(63),
"op" : "command",
"ns" : "admin.",
"query" : {
"currentOp" : 1
},
"numYields" : 0,
"locks" : {
},
"waitingForLock" : false,
"lockStats" : {
}
}
],
"ok" : 1
},
...
}

說明
client:發起請求的(de)客戶(hu)端。
opid:操(cao)作的唯一(yi)標識符。
secs_running:該操(cao)作已經執行的(de)時間,單位(wei):秒。如果該字段返回的(de)值特別(bie)大,需要查(cha)看請(qing)求(qiu)是否合(he)理。
microsecs_running:該操作已經執行的時(shi)間(jian),單位:微秒。如果該字段返回的值特別大,需要查(cha)看請求是(shi)否合理。
op:操(cao)作類型。通常是query、insert、update、delete、command中的一種。
ns:操作目標(biao)集(ji)合。
其他參數詳見db.currentOp()命令。
- 根據命令執行結果,分析是否有異常耗時的請求正在執行。
如(ru)果(guo)業(ye)務日常運(yun)行(xing)(xing)的CPU使用(yong)率不高,由(you)于執(zhi)行(xing)(xing)某一(yi)操作使得CPU使用(yong)率過高,導致業(ye)務運(yun)行(xing)(xing)緩慢,該場(chang)景下(xia),您需要關(guan)注執(zhi)行(xing)(xing)耗時久的請求。
如果發現異常請求,您可以找到該請求對應的opid,執行 db.killOp(opid) 命令終止該請求。
分析DDS數據庫的慢請求
文檔數(shu)據庫(ku)服務默認開啟了慢請求Profiling ,系統自(zi)動將(jiang)請求時間超過500ms的執行情況記錄(lu)到對應(ying)數(shu)據庫(ku)下的“system.profile”集合中。
- 通過Mongo Shell連接DDS實例。
開通公網訪問的實例
具體請參見:
未開(kai)通公網訪問的實例(li)
具體請參見:
- 執行以下命令,進入指定數據庫,以“test”為例。
use test
- 查看是否生成慢sql集合“system.profile”。
show collections;
- 回顯中有“system.profile”,說明產生了慢SQL,繼續執行下一步。
mongos> show collections
system.profile
test
- 回顯中沒有“system.profile”,說明未產生慢SQL,該數據庫不涉及慢請求分析。
mongos> show collections
test
- 查看數據下的慢請求日志。
db.system.profile.find().pretty()
- 分析慢請求日志,查找CPU使用率升高的原因。
下(xia)面是某個慢請(qing)求日志示例,可查看到該請(qing)求進行了全表掃描,掃描了1561632個文檔,沒(mei)有通過索(suo)引進行查詢。
{
"op" : "query",
"ns" : "taiyiDatabase.taiyiTables$10002e",
"query" : {
"find" : "taiyiTables",
"filter" : {
"filed19" : NumberLong("852605039766")
},
"shardVersion" : [
Timestamp(1, 1048673),
ObjectId("5da43185267ad9c374a72fd5")
],
"chunkId" : "10002e"
},
"keysExamined" : 0,
"docsExamined" : 1561632,
"cursorExhausted" : true,
"numYield" : 12335,
"locks" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(24672)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(12336)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(12336)
}
}
},
"nreturned" : 0,
"responseLength" : 157,
"protocol" : "op_command",
"millis" : 44480,
"planSummary" : "COLLSCAN",
"execStats" : {
"stage" : "SHARDING_FILTER", [3/1955]
"nReturned" : 0,
"executionTimeMillisEstimate" : 43701,
"works" : 1561634,
"advanced" : 0,
"needTime" : 1561633,
"needYield" : 0,
"saveState" : 12335,
"restoreState" : 12335,
"isEOF" : 1,
"invalidates" : 0,
"chunkSkips" : 0,
"inputStage" : {
"stage" : "COLLSCAN",
"filter" : {
"filed19" : {
"$eq" : NumberLong("852605039766")
}
},
"nReturned" : 0,
"executionTimeMillisEstimate" : 43590,
"works" : 1561634,
"advanced" : 0,
"needTime" : 1561633,
"needYield" : 0,
"saveState" : 12335,
"restoreState" : 12335,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 1561632
}
},
"ts" : ISODate("2019-10-14T10:49:52.780Z"),
"client" : "172.16.36.87",
"appName" : "MongoDB Shell",
"allUsers" : [
{
"user" : "__system",
"db" : "local"
}
],
"
在慢請求(qiu)日志中(zhong),您(nin)需要(yao)重(zhong)點關(guan)注(zhu)以下關(guan)鍵字(zi)。
- 全集合(全表)掃描:COLLSCAN
當一個操作請求(如query、update、delete)需要(yao)全表掃描時,將大(da)量占用CPU資源。在查(cha)看(kan)慢請求日志時,發現(xian)COLLSCAN關(guan)鍵字,很可(ke)能是(shi)這些查(cha)詢占用了CPU資源。
如(ru)果該類操作請(qing)求較為(wei)頻繁,建議(yi)您對查(cha)詢的字段建立索引(yin)進行(xing)優化(hua)。
- 全集合(全表)掃描:docsExamined
通過查(cha)看參數“docsExamined”的值,可以查(cha)看一(yi)個(ge)查(cha)詢掃描了多少文檔。該值越大,請求的CPU使用率越高。
- 不合理的索引:IXSCAN、keysExamined
說明索引不是越多越好,過多索引會影響寫入和更新的性能。
如果您的應用偏向于寫操作,建立索引可能會降低寫操作的性能。
通過查看參數“keysExamined”的(de)值(zhi),可以(yi)查看一個使(shi)用(yong)了(le)索(suo)(suo)引的(de)查詢,掃描了(le)多少條索(suo)(suo)引。該值(zhi)越大,請(qing)求的(de)CPU使(shi)用(yong)率越高(gao)。
如果索引建(jian)立不太合理,或者匹配的(de)結果很(hen)(hen)多(duo)。該場(chang)景(jing)下,即便使(shi)用了索引,請求的(de)CPU使(shi)用率也(ye)不會降(jiang)低很(hen)(hen)多(duo),執行的(de)速(su)度(du)也(ye)會很(hen)(hen)慢。
示例(li):對于某(mou)個集合的(de)數據,a字(zi)(zi)段的(de)取值(zhi)很少(shao)(只有1和2),而b字(zi)(zi)段的(de)取值(zhi)很多。
{ a: 1, b: 1 }
{ a: 1, b: 2 }
{ a: 1, b: 3 }
......
{ a: 1, b: 100000}
{ a: 2, b: 1 }
{ a: 2, b: 2 }
{ a: 2, b: 3 }
......
{ a: 1, y: 100000}
如下所示,要實現{a: 1, b: 2} 這樣的查詢。
db.createIndex( {a: 1} ) 效果不好,因為a相同取值太多
db.createIndex( {a: 1, b: 1} ) 效果不好,因為a相同取值太多
db.createIndex( {b: 1 } ) 效果好,因為b相同取值很少
db.createIndex( {b: 1, a: 1 } ) 效果好,因為b相同取值少
關于{a: 1}與{b: 1, a: 1}的區別,可參考。
- 大量數據排序:SORT、hasSortStage
當查詢請求中包(bao)含排(pai)序時(shi),“system.profile”集合中的(de)參數“hasSortStage”的(de)值為“true”。如果(guo)排(pai)序無(wu)法通過索(suo)引實現,將在查詢結果(guo)中進行排(pai)序。由于排(pai)序將占用(yong)大量CPU資源,該(gai)場景下,需要通過對經常排(pai)序的(de)字段建立索(suo)引進行優化。
當(dang)您在(zai)“system.profile”集合中發(fa)現SORT關鍵字時(shi),可以考慮(lv)通過索引來優化(hua)排序。
其他操作如建立索(suo)引、Aggregation(遍歷(li)、查(cha)詢、更(geng)新、排(pai)序(xu)等動作的組合(he))也可能占用大量CPU資源,但本(ben)質上也適(shi)用以上幾種場景。更(geng)多(duo)Profiling的設置,請參見。
分析服務能力
經過(guo)前面(mian)數(shu)據庫正在執行的(de)請(qing)(qing)求(qiu)和慢請(qing)(qing)求(qiu)的(de)分析和優化,所有的(de)請(qing)(qing)求(qiu)都使(shi)用了合(he)理的(de)索引,CPU的(de)使(shi)用率相對趨于穩定(ding)。如(ru)果(guo)經過(guo)前面(mian)的(de)分析排查(cha),CPU使(shi)用率仍然居高不下(xia),則可能是因為(wei)當前實例已達到(dao)性能瓶(ping)頸,不能滿(man)足(zu)業務需要,此時您可以通過(guo)如(ru)下(xia)方法解決。
- 通過查看監控信息分析實例資源的使用情況,請查看監控指標。
- 對DDS進行規格變更或者添加分片數量。