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 算子处理的数据量,从而加快计算速度。