標籤:back stat ble .so 存在 eth manual odata turned
背景
mongodb 提供了類sql的資料查詢及操作方式,同時也包含了彙總操作、索引等多個機制;
按以往的經驗,不當的庫表操作或索引模式往往會造成許多問題,如查詢操作緩慢、資料庫輸送量低下、CPU或磁碟IO飆升等問題。
因此在應用開發過程中,有必要對DB操作進行審視,尤其是關鍵業務或複雜條件查詢。mongodb 提供了explain方法可以讓我們
對 DB查詢語句進行分析,提前分析潛在的瓶頸。
查詢計劃
mongodb 通過查詢計劃(QueryPlan)描述一個查詢語句的執行過程,而通常一個查詢操作可能對應多組查詢計劃。
這些查詢計劃通過選舉機制產生最優計劃,作為最終的執行方案。此外mongodb 還提供了查詢計劃的緩衝機制,如:
圖 https://docs.mongodb.com/manual/_images/query-planner-diagram.bakedsvg.sv
Diagram of query planner logic
查詢操作被映射到一個查詢模型(query shape),模型中會包含條件(predicate)、排序(sort)、投影(projection)的定義;
以查詢模型作為Key尋找已存在的Plan緩衝,在找到緩衝的下一步仍進一步評估查詢效能,若效能評估結果未達標,則 mongodb會淘汰緩衝並進入查詢計劃產生階段。
每一個計劃產生階段都會包含:
- 產生候選計劃;
- 評估優選計劃;
- 競選最優計劃;
- 建立緩衝;
在產生最優計劃之後,查詢執行器將執行當前計劃併產生最終結果。
explain 操作
通過下面的語句,可以對當前查詢計劃展開分析
db.T_FooData.find({"appId":"s5WrMmrJV_8RBJG17FSVoY995Kga","nodeType":"SENSOR","creationTime":{ $gte : ISODate("2017-08-08T10:34:33.125Z"), $lt : ISODate("2017-08-08T12:34:33.125Z") }}).explain("executionStats")
輸出結果
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "db.T_FooData", "indexFilterSet" : false, "parsedQuery" : { "$and" : [ { "appId" : { "$eq" : "s5WrMmrJV_8RBJG17FSVoY995Kga" } }, { "nodeType" : { "$eq" : "SENSOR" } }, { "creationTime" : { "$lt" : ISODate("2017-08-08T12:34:33.125Z") } }, { "creationTime" : { "$gte" : ISODate("2017-08-08T10:34:33.125Z") } } ] }, "winningPlan" : { ... }, "rejectedPlans" : [ ... ], }, "executionStats" : { "executionSuccess" : true, "nReturned" : 62848, "executionTimeMillis" : 3058, "totalKeysExamined" : 1510833, "totalDocsExamined" : 1510833, "executionStages" : { ... } }, "serverInfo" : { "host" : "NB3000W_MongoDB_01", "port" : 50001, "version" : "3.4.7", "gitVersion" : "4249c1d2b5999ebbf1fdf3bc0e0e3b3ff5c0aaf2" }, "ok" : 1, "$gleStats" : { "lastOpTime" : Timestamp(1504498101, 1), "electionId" : ObjectId("7fffffff0000000000000001") }}
結果說明
explain 模式
mongodb 為 explain 操作提供了幾種模式:
- queryPlanner 預設的模式,僅進行查詢計劃分析,無法輸出執行過程統計;
- executionStats 執行模式,在查詢計劃分析後,將執行winningPlan並統計過程資訊;
- allPlansExecution 全計劃執行模式,將執行所有計劃(包括rejectPlans),並返回過程統計資訊;
executionStats.allPlansExecution 包含了所有計劃(除winningPlan之外)的執行過程統計資訊
執行計畫詳解
執行計畫將整個過程分解為多個階段,階段(stage)以樹狀結構組織,這點與執行過程是匹配的。
stage 分為多種類型,如下:
階段 |
描述 |
COLLSCAN |
全表掃描 |
IXSCAN |
索引掃描 |
FETCH |
根據索引去檢索指定document |
PROJECTION |
限定返回欄位 |
SHARD_MERGE |
將各個分區返回資料進行merge |
SORT |
表明在記憶體中進行了排序 |
LIMIT |
使用limit限制返回數 |
SKIP |
使用skip進行跳過 |
IDHACK |
針對_id進行查詢 |
SHARDING_FILTER |
通過mongos對分區資料進行查詢 |
COUNT |
利用db.coll.explain().count()之類進行count運算 |
COUNTSCAN |
count不使用用Index進行count |
COUNT_SCAN |
count使用了Index進行count |
SUBPLA |
未使用到索引的$or查詢 |
TEXT |
使用全文索引進行查詢 |
winningPlan 範例
"winningPlan" : { "stage" : "FETCH", "filter" : { "$and" : [ { "nodeType" : { "$eq" : "GATEWAY" } }, { "creationTime" : { "$lt" : ISODate("2017-08-08T12:34:33.125Z") } }, { "creationTime" : { "$gte" : ISODate("2017-08-08T10:34:33.125Z") } } ] }, "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "appId" : 1 }, "indexName" : "appId", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "appId" : [ "[\"s5WrMmrJV_8RBJG17FSVoY995Kga\", \"s5WrMmrJV_8RBJG17FSVoY995Kga\"]" ] } } },
欄位說明
屬性 |
描述 |
winningPlan.stage |
最優計劃stage,FETCH表示根據索引檢索文檔 |
winningPlan.filter |
最優計劃的過濾器,即查詢條件 |
winningPlan.inputStage |
最優計劃stage的child stage |
winningPlan.inputStage.stage |
child stage,此處是IXSCAN,表示進行index scanning |
winningPlan.inputStage.keyPattern |
掃描的索引模式 |
winningPlan.inputStage.indexName |
選用索引名稱 |
winningPlan.inputStage.isMultiKey |
是否是Multikey,如果索引建立在array上則為true |
winningPlan.inputStage.isSparse |
是否稀疏索引 |
winningPlan.inputStage.isPartial |
是否分區索引 |
winningPlan.inputStage.direction |
此query的查詢順序,此處是forward,如果用了.sort({w:-1})將顯示backward |
winningPlan.inputStage.indexBounds |
所掃描的索引範圍 |
過程統計詳解
executionStats 範例
"executionStats" : { "executionSuccess" : true, "nReturned" : 62848, "executionTimeMillis" : 3058, "totalKeysExamined" : 1510833, "totalDocsExamined" : 1510833, "executionStages" : { "stage" : "FETCH", "filter" : { "$and" : [ { "nodeType" : { "$eq" : "GATEWAY" } }, { "creationTime" : { "$lt" : ISODate("2017-08-08T12:34:33.125Z") } }, { "creationTime" : { "$gte" : ISODate("2017-08-08T10:34:33.125Z") } } ] }, "nReturned" : 62848, "executionTimeMillisEstimate" : 2765, "works" : 1510834, "advanced" : 62848, "needTime" : 1447985, "needYield" : 0, "saveState" : 11807, "restoreState" : 11807, "isEOF" : 1, "invalidates" : 0, "docsExamined" : 1510833, "alreadyHasObj" : 0, "inputStage" : { "stage" : "IXSCAN", "nReturned" : 1510833, "executionTimeMillisEstimate" : 792, "works" : 1510834, "advanced" : 1510833, "needTime" : 0, "needYield" : 0, "saveState" : 11807, "restoreState" : 11807, "isEOF" : 1, "invalidates" : 0, "keyPattern" : { "appId" : 1 }, "indexName" : "appId", "isMultiKey" : false, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "appId" : [ "[\"s5WrMmrJV_8RBJG17FSVoY995Kga\", \"s5WrMmrJV_8RBJG17FSVoY995Kga\"]" ] }, "keysExamined" : 1510833, "dupsTested" : 0, "dupsDropped" : 0, "seenInvalidated" : 0 } }}
欄位說明
屬性 |
描述 |
executionStats.executionSuccess |
是否執行成功 |
executionStats.nReturned |
返回條目數量 |
executionStats.executionTimeMilis |
執行時間(ms) |
executionStats.totalKeysExamined |
索引檢測條目 |
executionStats.totalDocsExamined |
文檔檢測條目 |
executionStats.executionStages |
執行階段詳情,大部分欄位繼承於winningPlan.inputStage |
executionStats.executionStages.stage |
執行階段,FETCH表示根據索引擷取文檔 |
executionStats.executionStages.nReturned |
階段返回條目數量 |
executionStats.executionStages.executionTimeMillisEstimate |
階段執行時間 |
executionStats.executionStages.docsExamined |
階段中文檔檢測條目 |
executionStats.executionStages.works |
階段中掃描任務數 |
executionStats.executionStages.advanced |
階段中向上提交數量 |
executionStats.executionStages.needTime |
階段中定位索引位置所需次數 |
executionStats.executionStages.needYield |
階段中擷取鎖等待時間 |
executionStats.executionStages.isEOF |
階段中是否到達流的結束位,對於limit限制符的查詢可能為0 |
executionStats.executionStages.inputStage |
執行階段的子階段,這裡是一個IXSCAN的子過程 |
參考文檔
explain 官方說明
http://www.mongoing.com/eshu_explain1
https://docs.mongodb.com/manual/reference/explain-results/#explain-output
關於explain的幾種模式
https://docs.mongodb.com/manual/reference/method/cursor.explain/
理解mongo 的查詢行為
https://www.compose.com/articles/explain-explain-understanding-mongo-query-behavior/
mongo的查詢快取
https://docs.mongodb.com/manual/core/query-plans/#index-filters
mongodb查詢操作分析