mongodb的查询过程

来源:互联网 发布:年度十大网络流行语 编辑:程序博客网 时间:2024/06/05 13:33
mongodb的查询过程是一个比较复杂的过程, 从查询语句到查询计划的执行, 中间经历了如下的几个步骤:
  1. 生成语法树 (matchExpression);
  2. 逻辑优化过程:由MatchExpression 生成 CanoncalQuery;
  3. 生成查询计划: 由CanoncalQuery生成QuerySolution和 MultiPlanStage;
  4. 生成PlanExecutor;
  5. 执行计划

    查询过程的流程图:
    这里写图片描述

    生成语法树

    从一个Bson类型的filter, 生成一个MatcgExpression 树, 具体的实现可以参考: http://blog.csdn.net/baijiwei/article/details/78127191 ;

逻辑优化过程

通过MatchExpression, 我们可以得到filter的所有的设定, 但是,这个设定可能是散乱的, 效率不高的, 逻辑优化过程的主要作用就是优化filter的设定, 使得在语义保持不变的前提下, 能够更加有效的执行。
该过程主要通过 CanonicalQuery 类来实现。
其实现细节可以参考: http://blog.csdn.net/baijiwei/article/details/78170387 。
该过程主要包含三个方面:
1、Normoralize tree;
2、sort tree;
3、 validate tree;

生成查询计划

通过CanonicalQuery 和MatchExpression, 类PlanEnumerator 罗列MatchExpression的各种可能的组合, (indexScan & collectionScan等), 生成具体的MatchExpression, 产生出来一个个的QueryPlan。 具体的实现在函数:QueryPlannerAccess::buildIndexedDataAccess, 生成一个树形的QuerySolutionNode树。
如果QuerySolution的个数大于1, 生成一个MultiPlanStage对象, 每个QuerySolution对应于一个PlanStage或者其子对象,planStage对象由函数StageBuilder::build 生成。
其实现细节可以参考: http://blog.csdn.net/baijiwei/article/details/78174198

生成 PlanExecutor

PlanExecutor::PlanExecutor(OperationContext* opCtx,                           unique_ptr<WorkingSet> ws,                           unique_ptr<PlanStage> rt,                           unique_ptr<QuerySolution> qs,                           unique_ptr<CanonicalQuery> cq,                           const Collection* collection,                           const string& ns)

如上述的代码片, 前面我们得到了PlanStage, QuerySolution以及CanonicalQuery, 可以生成一个指定的PlanExecutor, 查询计划的最终的执行是由该类的对象处理的。
生成最优的执行计划, MultiPlanStage::pickBestPlan最终选择由该函数实现, 具体的打分过程在PlanRanker::pickBestPlan.

执行查询计划

最终的执行过程非常简单: 遍历 PlanExecutor::getNextImpl

while (PlanExecutor::ADVANCED == (state = exec->getNext(&obj, NULL))) {       WorkingSetID id = WorkingSet::INVALID_ID;       PlanStage::StageState code = _root->work(&id);       WorkingSetMember* member = _workingSet->get(id);       bool hasRequestedData = true;       ...      if (hasRequestedData) {          _workingSet->free(id);          return PlanExecutor::ADVANCED;    } }

这里_root 是PlanStage*, 所有的planStage的ID保存在一个list里面:
std::list results;

函数PlanStage::work就是从前往后, 得到一个个的WorkingSetID。
相关的实现细节参考: http://blog.csdn.net/baijiwei/article/details/78195766

原创粉丝点击