Rule-based Optimizer(RBO)浅析 | 青训营笔记

247 阅读2分钟

image.png

Rule-based Optimizer(RBO)浅析

这是我参与「第四届青训营 」笔记创作活动的的第2天

引言

RBO是SQL引擎中基于规则对用户输出的SQL进行等价优化,是所有SQL引擎中性能优化中最为重要的一环。经过优化,在数据量非常大的时候可以减少大量的计算,减少 CPU 等资源的使用。本文将浅析部分RBO优化。

优化原则:

  • Read data less and faster
  • Transfer data less and faster
  • Process data less and faster

优化规则

列裁剪

提前将需要的列查询出来,其他不需要的列裁剪掉

例如表 t 有a b c d四列。 查询语句select a from t where b > 5 里面明显只有 a b 两列被用到了,所以 c d 的数据是不需要读取的。在查询计划里面,Selection 算子用到 b 列,下面接一个 DataSource 用到了 a b 两列,剩下 c 和 d 都可以裁剪掉,DataSource 读数据时不需要将它们读进来。

列裁剪的算法实现是自顶向下地把算子过一遍。某个结点需要用到的列,等于它自己需要用到的列,加上它的父亲结点需要用到的列。

列裁剪主要影响的算子是 Projection,DataSource,Aggregation。

例如

select s.name,s.sid,c.score from (select * from student where s.sid>100)s join (select * from course where c.score=100)c on s.sid=c.sid

会被优化为

select * from ( select name,sid from student where sid>100)s join (select score,sid from course where score=100)c on s.id=c.id

常量折叠

提前将常量表达式计算好

例如

select 100+100+c.score from course

会被优化为

select 200+c.score from course

谓词下推

在子查询阶段就提前将数据进行过滤,即将过滤条件尽可能地下推到底层,最好是数据源,这样处理之后后期 join 的 shuffle 数据量就大大减少

例如

select s.sid,c.score from student s join course c on s.sid=c.sid where s.name like 'liu%' and c.score>60

会被优化为

select s.sid,c.score from (select * from student where student.name like 'liu%')s join (select * from course where course.score>60) c on s.sid=c.sid

从上述语句可以看出,谓词下推将 Filter 算子直接下推到 Join 之前。也就是在扫描 student 表的时候使用条件过滤条件过滤出满足条件的数据;同时在扫描 course 表的时候会先使用 score>60 过滤条件过滤出满足条件的数据。经过这样的操作,可以大大减少 Join 算子处理的数据量,从而加快计算速度。

引用参考

Spark Sql源码详细分析

SparkSQL的执行流程(附常量折叠、谓词下推、列裁剪案例)