上篇文章我們介紹了索引的基本概念,描述了不同類型索引的差別,工欲善其事,必先利其器,這篇文章,我們将展開介紹 explain 這個執行計劃函數,進一步的了解Mongo的查詢計劃,來分析和診斷,提高查詢的效率。
explain()
是MongoDB的一個重要的查詢診斷工具,這個函數能夠提供大量與查詢相關的資訊,該函數會傳回查詢計劃、執行狀态、伺服器資訊,根據這些資訊可以有針對性的對性能進行優化。
- explain()函數
- explain() 傳回資訊
- explain() 使用示例
-
:{String},可選參數。指定冗長模式的解釋輸出,方式指定後會影響verbose
的行為及輸出資訊。可選值有:explain()
、"queryPlanner"
、"executionStats"
,預設為"allPlansExecution"
"queryPlanner"
queryPlanner 包括以下值:
- queryPlanner.namespace「運作查詢的指定命名空間」
- queryPlanner.indexFilterSet「表示MongoDB在查詢中是否使用索引過濾」
- queryPlanner.winningPlan「由查詢優化選擇的計劃」
winningPlan.stage「表示查詢階段的字元串」
winningPlan.inputStage「表示子過程的文檔」
winningPlan.inputStages「表示子過程的文檔數組」
queryPlanner.rejectedPlans「被查詢優化備選并被拒絕的計劃數組」
executionStats「被選中執行計劃和被拒絕執行計劃的詳細說明」
queryPlanner.nReturned「比對查詢條件的文檔數」
queryPlanner.executionTimeMillis「計劃選擇和查詢執行所需的總時間(毫秒數)」
queryPlanner.totalKeysExamined「掃描的索引總數」
queryPlanner.totalDocsExamined「掃描的文檔總數」
queryPlanner.executionStages「顯示執行成功細節的查詢階段樹」
executionStages.works「指定查詢執行階段執行的“工作單元”的數量」
executionStages.advanced「傳回的中間結果數」
executionStages.needTime「未将中間結果推進到其父級的工作周期數」
executionStages.needYield「存儲層要求查詢系統産生的鎖的次數」
executionStages.isEOF「指定執行階段是否已到達流結束」
queryPlanner.allPlansExecution「包含在計劃選擇階段期間捕獲的部分,包括選擇計劃和拒絕計劃」
serverInfo:「MongoDB執行個體的相關資訊」
winningPlan.shards「包括每個通路片的queryPlanner和serverInfo的文檔數組」
下圖展示如何選擇查詢計劃

執行 db.persons.find({age:10}).explain("executionStats")我們看具體的explain計劃
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "Performance.persons", --資料庫名+集合的名稱
"indexFilterSet" : false,
"parsedQuery" : {
"age" : {
"$eq" : 10.0 -- 生成原生的查詢 {age:10}
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0,
"name" : 1.0
},
"indexName" : "age_1_name_1",
"isMultiKey" : false, -- 多Key索引
"multiKeyPaths" : { -- 複合索引的Key Path
"age" : [],
"name" : []
},
"isUnique" : false, -- 唯一索引
"isSparse" : false, -- 稀疏索引
"isPartial" : false, -- 部分索引
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : { -- 索引的查詢範圍
"age" : [
"[10.0, 10.0]"
],
"name" : [
"[MinKey, MaxKey]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : { -- 執行計劃的統計
"executionSuccess" : true,
"nReturned" : 2, -- 查詢得到的文檔數目
"executionTimeMillis" : 2, -- 查詢消耗的毫秒數
"totalKeysExamined" : 2, -- 索引掃描的數量
"totalDocsExamined" : 2, -- 文檔掃描的數量
"executionStages" : {
"stage" : "FETCH",
"nReturned" : 2,
"executionTimeMillisEstimate" : 0,
"works" : 3, -- 工作單元
"advanced" : 2, --傳回的中間數
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1, -- 遊标的末尾
"invalidates" : 0,
"docsExamined" : 2,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 2,
"executionTimeMillisEstimate" : 0,
"works" : 3,
"advanced" : 2,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"age" : 1.0,
"name" : 1.0
},
"indexName" : "age_1_name_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"age" : [],
"name" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[10.0, 10.0]"
],
"name" : [
"[MinKey, MaxKey]"
]
},
"keysExamined" : 2,
"seeks" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : { -- server information
"host" : "bogon",
"port" : 27017,
"version" : "4.0.3",
"gitVersion" : "7ea530946fa7880364d88c8d8b6026bbc9ffa48c"
},
"ok" : 1.0
}
基礎知識準備的差不多了,下一篇我們将就慢查詢優化,展開讨論,讓我們一起來見證奇迹的發生.........
參考文章
Query Plans - MongoDB Manualdocs.mongodb.com
planCacheListFilters - MongoDB Manualdocs.mongodb.com
planCacheClearFilters - MongoDB Manualdocs.mongodb.com
planCacheSetFilter - MongoDB Manualdocs.mongodb.com
cursor.hint() - MongoDB Manualdocs.mongodb.com
Explain Results - MongoDB Manualdocs.mongodb.com
Glossary - MongoDB Manualdocs.mongodb.com
https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.updatedocs.mongodb.com