關於mongodb索引 explain()函數的測試
dbtest表數據結構 : {a:“1”,b:“1”,c:“1”,d:“1”,e:“1”},
dbtest表:
索引1:abcde ,
查詢條件:abc 執行索引1,
查詢條件:ac 執行索引1,
查詢條件:ace 執行索引1,
查詢條件:aeb 執行索引1,
查詢條件:bc 不執行索引1,
查詢條件:dbc 不執行索引1,
查詢條件:kbc 不執行索引1, k不存在索引鍵,
單索引.按查詢條件的首鍵,必須是索引鍵的首鍵才能執行索引,並且查詢條件內更多字段與單索引的鍵的排序匹配,查詢效率更高
dbtest表:
索引1:abcde
索引2:bcd
查詢條件:bc 執行索引1,
查詢條件:dba 執行索引2, 拒絕執行索引1
查詢條件:dbc 執行索引2,
查詢條件:dbe 執行索引2,
查詢條件:kbce 執行索引2, k不存在索引鍵,
查詢條件:kdbe 執行索引2, k不存在索引鍵,
查詢條件:kbe 執行索引2, k不存在索引鍵,
查詢條件:kae 執行索引1, k不存在索引鍵,
雙索引時,可不按查詢條件與條件的索引順序進行排序,但未能保證查詢效率最優
dbtest表:
索引1:cd
索引2:abe,
查詢條件:cd 執行索引1,
查詢條件:bc 執行索引1, 索引2的b不是索引首鍵,無法匹配
查詢條件:ca 執行索引1, 拒絕執行索引2
查詢條件:ac 執行索引2,
dbtest表:
索引1:cd
索引2:abe,
索引3:ac,
查詢條件:ca 執行索引1, 拒絕執行索引2和索引3
查詢條件:ac 執行索引1, 拒絕執行索引2和索引3
dbtest表數據結構 : {a:"1",b:"1",c:"1",d:"1",e:"1"},
索引1:cd
索引2:abe,
索引3:ac,
查詢語句: db.getCollection("dbtest").find({a:"1",c:"1"}).explain()
判斷是否有啓用索引: winningPlan.inputStage.IXSCAN 可選項:COLLSCAN 沒有走索引;IXSCAN使用了索引) , rejectedPlans(候選的執行計劃) executionStats(執行情況描述)
winningPlan.inputStage.indexBounds 查詢優化器針對該查詢所返回的最優執行計劃的詳細內容 {"a":["[\"1\", \"1\"]"],"b":["[MinKey, MaxKey]"]} , "[\"1\", \"1\"]",是根據查詢條件傳的值進行提示, MinKey是查詢條件該索引用不到這個建
rejectedPlans.inputStage.indexBounds 其他執行計劃(非最優而被查詢優化器拒絕的)
利用mongodb 4.0數據庫版本, 測試索引時,返回的結果,與3.x版本還有點差異,但下面的鏈接可以參考
{
"queryPlanner" : { // (執行計劃描述) 是默認值,表示僅僅展示執行計劃信息;
"plannerVersion" : 1.0,
"namespace" : "1004.dbtest",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [{"a":{"$eq":"1"}},{"c":{"$eq":"1"}}]
},
"winningPlan" : { //查詢優化器針對該查詢所返回的最優執行計劃的詳細內容
"stage" : "FETCH",
"filter" : {"a":{"$eq":"1"}},
"inputStage" : {
"stage" : "IXSCAN", //(可選項:COLLSCAN 沒有走索引;IXSCAN使用了索引) rejectedPlans(候選的執行計劃) executionStats(執行情況描述)
"keyPattern" : {"c":1.0,"d":1.0},
"indexName" : "c_1_d_1",
"isMultiKey" : false,
"multiKeyPaths" : {"c":[],"d":[]},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {"c":["[\"1\", \"1\"]"],"d":["[MinKey, MaxKey]"]}
}
},
"rejectedPlans" : [ // 其他執行計劃(非最優而被查詢優化器拒絕的)
{
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN", //(可選項:COLLSCAN 沒有走索引;IXSCAN使用了索引) rejectedPlans(候選的執行計劃) executionStats(執行情況描述)
"keyPattern" : {"a":1.0,"c":1.0},
"indexName" : "a_1_c_1",
"isMultiKey" : false,
"multiKeyPaths" : {"a":[],"c":[]},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {"a":["[\"1\", \"1\"]"],"c":["[\"1\", \"1\"]"]}
}
},
{
"stage" : "FETCH",
"filter" : {"c":{"$eq":"1"}},
"inputStage" : {
"stage" : "IXSCAN", //(可選項:COLLSCAN 沒有走索引;IXSCAN使用了索引) rejectedPlans(候選的執行計劃) executionStats(執行情況描述)
"keyPattern" : {"a":1.0,"b":1.0,"e":1.0},
"indexName" : "a_1_b_1_e_1",
"isMultiKey" : false,
"multiKeyPaths" : {"a":[],"b":[],"e":[]},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2.0,
"direction" : "forward",
"indexBounds" : {"a":["[\"1\", \"1\"]"],"b":["[MinKey, MaxKey]"],"e":["[MinKey, MaxKey]"]}
}
}
]
},
"ok" : 1.0,
"operationTime" : Timestamp(1588144252, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1588144252, 1),
"signature" : {
"hash" : BinData(0, "7VNm3KvacDc03o4NGrBSLQvdsKY="),
"keyId" : NumberLong(6776055669654028289)
}
}
}
參考的鏈接
explain.queryPlanner.namespace 顧名思義,該值返回的是該query所查詢的表。
explain.queryPlanner.indexFilterSet 針對該query是否有indexfilter(會在後文進行詳細解釋)。
explain.queryPlanner.winningPlan 查詢優化器針對該query所返回的最優執行計劃的詳細內容。
explain.queryPlanner.winningPlan.stage 最優執行計劃的stage,這裏返回是FETCH,可以理解爲通過返回的index位置去檢索具體的文檔
explain.queryPlanner.winningPlan.stage的child stage,此處是IXSCAN,表示進行的是index scanning。
explain.queryPlanner.winningPlan.keyPattern 所掃描的index內容,此處是w:1與n:1。
explain.queryPlanner.winningPlan.indexName winning plan所選用的index。
explain.queryPlanner.winningPlan.isMultiKey 是否是Multikey,此處返回是false,如果索引建立在array上,此處將是true。
explain.queryPlanner.winningPlan.direction 此query的查詢順序,此處是forward,如果用了.sort({w:-1})將顯示backward。
explain.queryPlanner.winningPlan.indexBounds winningplan所掃描的索引範圍,此處查詢條件是w:1,使用的index是w與n的聯合索引,故w是[1.0,1.0]而n沒有指定在查詢條件中,故是[MinKey,MaxKey]。
explain.queryPlanner.rejectedPlans 其他執行計劃(非最優而被查詢優化器reject的)的詳細返回,其中具體信息與winningPlan的返回中意義相同,故不在此贅述。
COLLSCAN //全表掃描
IXSCAN //索引掃描
FETCH //根據索引去檢索指定document
SHARD_MERGE //將各個分片返回數據進行merge
SORT //表明在內存中進行了排序(與老版本的scanAndOrder:true一致)
LIMIT //使用limit限制返回數
SKIP //使用skip進行跳過
IDHACK //針對_id進行查詢
SHARDING_FILTER //通過mongos對分片數據進行查詢
COUNT //利用db.coll.explain().count()之類進行count運算
COUNTSCAN //count不使用用Index進行count時的stage返回
COUNT_SCAN //count使用了Index進行count時的stage返回
SUBPLA //未使用到索引的$or查詢的stage返回
TEXT //使用全文索引進行查詢時候的stage返回
PROJECTION //限定返回字段時候stage的返回
對於普通查詢 我們最希望看到的組合有以下這些 Fetch+IDHACK; Fetch+ixscan; Limit+(Fetch+ixscan); PROJECTION+ixscan; SHARDING_FILTER+ixscan; 不希望看到的有以下這些 COLLSCAN(全表掃); SORT(使用sort但是無index); 不合理的SKIP; SUBPLA(未用到index的$or);
對於count查詢 我們希望看到的有:COUNT_SCAN;不希望看到的有:COUNTSCAN
所以,當查詢覆蓋精確匹配,範圍查詢與排序的時候,精確匹配字段,排序字段,範圍查詢字段,這樣的索引排序會更爲高效。