mongodb的查询过程

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值