上接:Presto - Coordinator 查询流程-4,上章讲到逻辑计划的构建,生成了PlanNode root,逻辑计划,本章将继续讲解逻辑计划的优化;
1. 逻辑计划 Plan
逻辑计划优化代码入口在LogicalPlanner#plan方法中的如下代码片段;
for (PlanOptimizer optimizer : planOptimizers) { // 优化
root = optimizer.optimize(root, session, symbolAllocator.getTypes(), symbolAllocator, idAllocator, warningCollector);
requireNonNull(root, format("%s returned a null plan", optimizer.getClass().getName()));
}
2. Optimizer
优化是通过Optimizers实现的,每一个Optimizer都通过vistor模式修改逻辑计划树,在不修改查询意图的基础上,加速查询;Presto实现的Optimizer比较少,只有最基本如LimitPushDown, IndexJoinOpitimizer;如果有意向深入的了解优化器,可以查看Spark的优化器;在Presto中有一个AddExchange优化器比较特殊,给逻辑计划树添加Exchange节点,标志这个地方需要执行数据交换,后续会根据Exchange节点切分逻辑计划,生成分布式的逻辑计划;
2.1 优化器的功能
- 常量折叠
- 算子(条件,选择)下推
- 算子重写,比如Distinct重写成groupby语句
- 算子结合,Union结合,Project结合,Filter结合等
- 代码生成,比如大量case when会生成代码
- 子查询递归优化
- 文件数据源的下推,比如pruneFileSourcePartitions
2.1 AddExchange
AddExchange是Presto中体比较特殊优化器,用于后续切分逻辑计划, 可能添加Exchange的地方包括, Aggregate节点,Join节点,Distinct节点,Window节点等;添加Exchange逻辑不相同,可以理解为需要shuffle的地方都会添加ExchangeNode;