高性高mongodb之執行計劃

我的專欄地址:我的segmentfault,歡迎瀏覽


一、執行計劃介紹

MongoDB 3.0之後,explain的返回與使用方法與之前版本有了不少變化,介於3.0之後的優秀特色,本文僅針對MongoDB 3.0+的explain進行討論。
現版本explain有三種模式,分別如下:

  • queryPlanner
  • executionStats
  • allPlansExecution

其中 queryPlanner 是現版本explain的默認模式,queryPlanner模式下並不會去真正進行query語句查詢,而是針對query語句進行執行計劃分析並選出winning plan。


舉個執行計劃的命令例子:
db.usertable.find({"w": 1}).explain("queryPlanner")


舉個執行計劃響應結果的例子:
{
    "queryPlanner":{
        "plannerVersion":1,
        "namespace":"game_db.game_user", #該值返回的是該query所查詢的表
        "indexFilterSet":false, #是否應用了index filter
        "parsedQuery":{ #查詢條件
            "w":{
                "$eq":1
            }
        },
        "winningPlan":{ #查詢優化器針對該query所返回的最優執行計劃的詳細內容
            "stage":"FETCH", #最優執行計劃的stage,這裏返回是FETCH,可以理解爲通過返回的index位置去檢索具體的文檔
            "inputStage":{ # #explain.queryPlanner.winningPlan.stage的child stage,此處是IXSCAN,表示進行的是index scanning。
                "stage":"IXSCAN", #索引查找
                "keyPattern":{ #所掃描的index內容,此處是w:1與n:1。
                    "w":1,
                    "n":1
                },
                "indexName":"w_1_n_1", #winning plan所選用的index。
                "isMultiKey":false, #本次查詢是否使用了多鍵、複合索引
                "direction":"forward", #此query的查詢順序,此處是forward,如果用了.sort({w:-1})將顯示backward。
                "indexBounds":{ #winningplan所掃描的索引範圍,此處查詢條件是w:1,使用的index是w與n的聯合索引,故w是[1.0,1.0]而n沒有指定在查詢條件中,故是[MinKey,MaxKey]。
                    "w":[
                        "[1.0, 1.0]"
                    ],
                    "n":[
                        "[MinKey, MaxKey]"
                    ]
                }
            }
        },
        "rejectedPlans":[ #其他執行計劃(非最優而被查詢優化器reject的)的詳細返回,其中具體信息與winningPlan的返回中意義相同,故不在此贅述。
            {
                "stage":"FETCH",
                "inputStage":{
                    "stage":"IXSCAN",
                    "keyPattern":{
                        "w":1,
                        "v":1
                    },
                    "indexName":"w_1_v_1",
                    "isMultiKey":false,
                    "direction":"forward",
                    "indexBounds":{
                        "w":[
                            "[1.0, 1.0]"
                        ],
                        "v":[
                            "[MinKey, MaxKey]"
                        ]
                    }
                }
            }
        ]
      },
    "serverInfo" : {
            "host" : "ALI-SZ-VT-TEST001",
            "port" : 27017,
            "version" : "4.0.5",
            "gitVersion" : "3739429dd92b92d1b0ab120911a23d50bf03c412"
      },
      "ok" : 1
}

二、queryPlanner學習

2.1 Stage的意義

explain.queryPlanner.winningPlan.stageexplain.queryPlanner.winningPlan.inputStage**等。

stage/inputStage值 值的意義
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的返回

2.2一個stage/inputStage的特點

執行一:

db.usertable.find({"field0": "use"}).explain("queryPlanner")
{
      ...
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "field0" : {
                    "$eq" : "use"
                }
            },
            "direction" : "forward"
        },
        ...
}

執行二:

db.usertable.find({"field0": "use"}).limit(1).explain("queryPlanner")
{
    ...
        "winningPlan" : {
            "stage" : "LIMIT",
            "limitAmount" : 1,
            "inputStage" : {
                "stage" : "COLLSCAN",
                "filter" : {
                    "field0" : {
                        "$eq" : "use"
                    }
                },
                "direction" : "forward"
            }
        },
        ...
}

執行二在執行一的基礎上增加了 limit限掉, queryPlanner由 stage(COLLSCAN) 變成了 stage(LIMIT)、inputStage.stage(COLLSCAN)。說明在判斷queryPlanner是否達到用戶想要的效果要對 stageinputStage.stag綜合考慮。

參考文章:

MongoDB乾貨系列2-MongoDB執行計劃分析詳解 http://www.mongoing.com/eshu_explain2
官方文檔: https://docs.mongodb.com/manual/tutorial/analyze-query-plan/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章