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

...

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