1.3.3 查询优化器
除了查询执行层面的优化,Doris在查询优化器方面也做了大量改进。Doris中的查询优化器能够同时进行基于规则和基于代价的查询优化。在基于规则的查询优化方面,Doris完成了包括但不限于以下方面的改进。
1)常量折叠。常量折叠可以预先对常量表达式进行计算,计算后的结果有助于规划器进行分区分桶裁剪,以及执行层利用索引进行数据过滤等。例如将where event_dt>=cast(add_months(now(),-1)as date)折叠成where event_dt>=2022-02-20。
2)子查询改写。将子查询改写为Join操作,从而利用Doris在Join算子上做的一系列优化来提升查询效率,例如将select*from tb1 where col1 in(select col2 from tb2)a改写成select tb1.*from tb1 inner join tb2 on tb1.col1=tb2.col2。
3)提取公共表达式。提取公共表达式可以将SQL中的一些析取范式转换成合取范式,而合取范式通常对执行引擎是比较友好的,可以将查询条件重组或者下推,减少数据扫描和读取的行数,例如将条件where(a>1 and b=2) or (a>1 and b=3) or (a>1 and b=4)转化成where a>1 and b in (2,3,4),明显后者的判断速度比前者的快很多。
4)智能预过滤。智能预过滤可以将SQL中的析取范式转换成合取范式并提炼出公共条件,以便预先过滤部分数据,从而减少数据处理量。
5)谓词下推。Doris中的谓词下推不仅可以穿透查询层,还能进一步下推到存储层,利用索引进行数据过滤,如图1-15所示。
图1-15 Doris中的谓词下推示意图
而在基于代价的查询优化方面,Doris主要针对Join算子进行了大量优化。
Join Reorder可以通过一些表的统计信息,自动调整Join顺序。而Join顺序的调整可有效减小Join操作中生成的中间数据集的大小,从而加速查询的执行,如图1-16所示。
图1-16 Join Reorder优化示意图
Colocation Join可以利用数据的分布情况,将原本需要去重后才能进行关联的数据,在本地完成关联,从而避免去重时大量的数据传输,如图1-17所示。
图1-17 Colocation Join优化示意图
Bucket Join是Colocation Join的通用版本。Colocation Join需要用户在建表时就指定表的分布,以保证需要关联查询的若干表有相同的数据分布。而Bucket Join会更智能地判断SQL中关联条件和数据分布之间的关系,将原本需要同时去重左右两张表中数据的操作,变成将右表数据重分布到左表所在节点,从而减少数据的移动,如图1-18所示。
图1-18 Bucket Join优化示意图