Drill中Calcite优化器代码分析

什么是优化器

优化器是对关系节点树做等价变换得到最小代价的执行计划的组件。

优化器执行框架涉及的主要概念如下: 

优化规则(RelOptRule):可对关系节点进行等价转换,包括规则模式定义,模式识别,规则执行,执行关联操作等步骤。

关系集合(RelSet):包含具有不同特性集的关系子集合,一般和关系节点树的根节点对应。

关系子集合(RelSubSet):具有相同特性集合的关系节点组成,特性集和关系子集和一一对应。

特性(RelTrait):目前calcite有排序和转换两种特性,drill包含了分布的特性。特性作用于关系节点。特性是一类优化规则的集合,也是开关。

特性定义(RelTraitDef): calcite中包含ConventionTraitDef和RelCollationTraitDef。ConventionTraitDef内部为特性转换图,边为规则,节点为特性,通过添加规则来构造图,和ConverterRule接口的优化规则配合进行关系节点优化;RelCollationTraitDef主要用于与排序相关的关系节点的优化。

转换器规则(ConverterRule):以特性和关系表达式为操作对象,以特性转换为操作内容,以相同语义关系表达式为操作结果,添加规则过程是构建特性定义ConventionTraitDef中特性转换图的过程。

这些概念串联起来可表述为:优化规则(RelOptRule)把具有一种特性集(RelTraitSet)的关系节点(RelNode)转换到另一种特性集的关系节点, 特性需要有特性定义(RelTraitDef),特性转换需要有转换器(AbstractConverter),同一关系集(RelSet)内关系子集(RelSubSet)之间是等价关系,相同特性集的关系节点组成关系子集。优化器从等价的关系集中找出最优。

Calcite中优化器执行框架

一个优化规则的例子:

JoinAssociateRule规则的模式如下:

private JoinAssociateRule() {
super(
operand(Join.class,
operand(Join.class, any()),
operand(RelSubset.class, any())));
}

优化过程如图:

             topJoin                            newTopJoin
             /        \                                /           \
 bottomJoin     C          =>             A         newBottomJoin
    /          \                                                     /           \
  A            B                                                B             C

下面是关键步骤的说明

优化器创建和特性添加

Frameworks.withPrepare

         CalcitePrepareImpl.perform.createPlanner

                   VolcanoPlanner.addRelTraitDef

优化器执行过程

PlannerImpl.transform//calcite优化执行入口

         RuleSetProgram.run//一次运行多个优化规则

                   VolcanoPlanner.addRule//添加优化规则

                            ConventionTraitDef.registerConverterRule//注册转换器规则,内部会创建抽象转换器把源特性转换为目标特性

                                     ConverterRule.getInTrait//获取源特性或者目标特性

                                               ConversionData.conversionGraph//构造特性转换图

                   ValcanoPlanner.setRoot.registerImpl//setroot中包含根关系节点和后裔节点的注册过程

                            AbstractRelNode.onRegister//触发子关系节点注册

                                     ValcanoPlanner.ensureRegistered//在RelSet注册原始关系节点,添加RelSubSet,递归注册

                            RelSet//为根表达式生成RelSet

                            ValcanoPlanner.asd//生成子集,等价集

                                     RelSet.add.getOrCreateSubset//创建或者将关系节点加入具有相同特性集合的子集,在RelSet中注册转换器关系节点

                                               AbstractConverter//特性转换器抽象类,需要ExpandConversionRule生效才能触发执行

                                               ValcanoPlanner.register.checkForSatisfiedConverters.changeTraitsUsingConverters.registerImpl

                            registerClass//注册关系表达式自己的规则

                                     JdbcConvention.register//注册特性相关的规则

                            ValcanoPlanner.fireRules//触发规则执行

                                     DeferringRuleCall.match//推迟执行规则

                                               ValcanoPlanner.ruleQueue.addMatch//生成推迟执行的规则队列

                                     VolcanoRuleCall.match//规则匹配开始

                   VolcanoPlanner.findBestExp//找到代价最小的关系节点

                            RuleQueue.popMatch//推迟执行的规则现在开始执行

                                     VolCanoRuleMatch.onMatch//开始规则执行

                                               RelOptRule.onMatch//执行定制的优化规则

                                                        VolcanoRuleCall.transformTo//在RelSet中注册转换后的关系节点,作为原始关系节点的等价节点

                                                                 RelTraitPropagationVisitor//原始关系节点特性传播到等价节点

                                                                 VolcanoPlanner.ensureRegistered//注册等价关系节点

                            RelSubSet.buildCheapestPlan//找到最小代价

                                     CheapestPlanReplacer.visit

                                               RelSubSet.best//RelSubSet创建时有一个初始值,关系子集中每次添加新的关系节点时这个值随之变化。

                                               VolcanoPlanner.provenanceMap.put//追踪关系节点变化过程

 

AbstractConverter触发执行的过程

ExpandConversionRule.onMatch//只能通过ExpandConversionRule触发执行AbstractConverter

         AbstractConverter.getInput

         VolcanoPlanner.changeTraitsUsingConverters

                   ConventionTraitDef.convert.changeConvention

                            ConverterRule.convert

                                     RelOptRule.convert

规则匹配过程

RelOptRule//规则匹配前预处理

         flattenOperands//获取操作符的前序优先遍历集合

         assignSolveOrder//构建每个操作符的匹配顺序,首先是自身,然后是父节点直到根节点,最后是前序遍历数组中其它节点

VolcanoRuleCall.match//利用RelOptRule.assignSolveOrder中提供的匹配顺序,规则对应的模式树的匹配可以从模式树的任一节点开始,匹配过程提供了向上的多条路径,但只有一条路径是符合原有模式的,不符合的路径在solveOrder达到operands的大小前自动终止。具体匹配过程比较复杂,详见VolcanoRuleCall.matchRecurse.

Drill优化逻辑

drill中物理执行计划优化规则指DrillRuleSets.getPhysicalRules中包含的优化规则
drill中逻辑执行计划优化规则指DrillRuleSets.getDrillBasicRules中和包含的优化规则
其它都是calcite中的优化规则,drill中优化规则补充或者取代了calcite中的规则

drill中的逻辑执行计划优化规则

1.DrillScanRule,DrillFilterRule,DrillProjectRule,DrillWindowRule,DrillWindowRule,DrillUnionRule
对子节点递归处理,无实质优化,仅是将calcite关系节点转换为drill关系节点
2. DrillJoinRule
join on中如果包含join字段和过滤条件,先filter再inner join
3.DrillLimitRule
将calcite中SortRel节点记录的关于limit的信息去掉,在drill的逻辑执行计划中独立出一个DrillLimitRel节点
4.DrillSortRule
此规则中匹配的模式和DrillLimitRule中一样,但在matches方法中做了区别,所以遇到同样的SortRel节点会匹配到不同的规则。
5.DrillPushPartitionFilterIntoScan
如果filter中字段是partition字段,则GroupScan过程中获取文件路径的步骤改为直接获取filter字段对应的文件路径。

drill中的物理执行计划优化规则

此处优化主要关注计算的分布执行。优化方法如下。优化不足之处如join中数据倾斜等问题暂无优化,这样drill和hive中优化方法可以互相借鉴补充。
1.ConvertCountToDirectScan
将select count(*/columnname) from tbl形式的语句中GroupScan步骤改为DirectGroupScan,并添加DrillDistributionTrait特性
2.HashAggPrule
关于聚合函数的优化。如果聚合函数中包含需要获得全局信息的distinct语句,或者不包含用于数据分布的分组列则优化不能执行。
hash agg分两种策略:对所有分组字段进行分布或者仅对单个分组字段进行分布。
对分组字段进行分布后得到部分分组聚合结果,在TwoPhaseSubset类中OperatorPhase.PHASE_1of2步骤对应对HashAggPrel是分组字段分布后的hash agg得到的结果,HashToRandomExchangePrel中会建立sender, receiver分发数据和收集返回的结果,OperatorPhase.PHASE_2of2步骤对应的HashAggPrel中phase1Agg.getPhase2AggCalls()函数得到的结果是已经对原来关系节点添加了SqlSumCountAggFunction函数的AggregateCall节点。
3.StreamAggPrule
与HashAggPrule类似
4.HashJoinPrule,MergeJoinPrule
关于join三种实现方法hash join, merge join, nested loop的优化。对nested loop的优化在老的optiq中类名为NestedLoopsJoinRule,在新的calcite中类名为JoinToCorrelateRule,主要在逻辑执行计划阶段进行优化,没有在物理执行计划阶段优化。drill中目前只用到了PhysicalJoinType {HASH_JOIN, MERGE_JOIN}这两种join方式的优化。
HashJoinPrule:join右边节点结果行数如果小于100万这个阈值,则对右边节点添加BROADCAST_DISTRIBUTED特性进行广播分发,并且因为结果行数较少,放入内存计算。主要代码在checkBroadcastConditions函数和createBroadcastPlan函数中。
MergeJoinPrule:此优化方法是基于HashJoinPrule中的优化方法,但还需要为join两边节点添加collation特性,merge join是先sort,然后通过merge来做join.
5.其它实现了Prule抽象类的物理计划优化规则无实质优化,主要是做drill logical plan到drill physical plan的无优化转换。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页