PlanExecutor 和 getExecutor() 主要流程 -- MongoDB

PlanExecutor:

總的來說是一個根據內部的執行樹(Execution Tree)從數據庫中獲取數據的一個上層抽象結構/接口,在Query Engine執行find()時就用這貨獲取數據,它還用於與查詢優化器(Query Optimizer)或Cache等交互。

主要對外接口: 一系列的make()用於構建PlanExecutor. 服務於其本身的工廠設計模式,

  1. static StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> make(…) 構建一個PlanExecutor一般情況下需要CanonicalQuery(CQ),但不是必須的,比如Aggregate query可能創建個PlanExecutor用於獲取數據,但不提供CQ
  2. ExecState getNext(Document* objOut, RecordId* dlOut): 用於從數據庫獲取數據 ...

主要內部成員:

  1. WorkingSet: 是MongoDB用來存放於內存的數據工作集,例如當PlanExecutor在一步一步執行getNext()過去數據的時候,獲取的數據都是存入WorkingSet的。getNext()返回執行結果的同時返回給caller的RecordId* dlOut正是用於從WorkingSet中獲取數據的ID.
  2. QuerySolution: 所用的Query Solution
  3. PlanStage: Query Solution對應的真正用於執行獲取數據的數據結構。 ...

getExecutor() 主要流程:

Return value:

struct PrepareExecutionResult {
    ...

    unique_ptr<CanonicalQuery> canonicalQuery;  // 可能會被修改

    // 查詢樹. 內部是一個查詢樹(節點爲QuerySolutionNode),代表一個Query Plan, 可用於生成PlanStage tree.
    unique_ptr<QuerySolution> querySolution; 	

    // 對應Query Plan的 Query Execution Plan(QEP), 真正用於獲取數據的底層數據結構。
    unique_ptr<PlanStage> root;
};

主要流程:  prepareExecution() -> PlanExecutor::make() 

prepareExecution(): 爲特定Query(canonicalQuery)構建一個執行樹(Execution Tree).

1) 準備QueryPlannerParams(Query Planner需要的參數), 比如選擇可用的indexes(過濾掉不可用的index,比如當用戶設置了index filters的時候,或者被用戶隱藏的index(V4.4開始,用戶可以隱藏index, 見SERVER-26589))

2) 準備IdHack Plan(當Query Planner決定使用_id索引的時候)

3) 查Cache是否有Cached Plan可以用

4) QueryPlanner::plan()(產出備選query solutions/plans), 如果備選query solutions大於一個的話,則會有一個MultiPlanStage作爲最後Query Plan的root stage,該stage之後排序,選擇最佳Query Solution用於該Query獲取數據.(Link Token: [TODO],哪天有空再補個Mongo如何選擇最佳query plan的筆記吧...)

5) Misc. 其他優化...

PlanExecutor::make() : 構建PlanExecutor

...

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