SQL优化技巧 - 查询折叠
· 阅读需 6 分钟
问题定义
查询折叠(Query Folding)指的是把查询中的视图、CTE或是DT子查询展开,并与引用它的查询语句合并,从而减少查询语句的子查询数目,降低其复杂度的一种优化算法。其收益有以下三个方面:
- 避免中间结果集的物化
- 启用更多的连接顺序规划
- 提供更多的索引建议机会(PawSQL索引推荐引擎)
考虑下面的例子,
SELECT * FROM (SELECT c_custkey, c_name FROM customer) AS dt;
重写后的SQL为,
SELECT c_custkey, c_name FROM customer
注1. 在下文中,我们将使用“视图”一词,但所有描述也适用于CTE或是DT子查询。
注2. 本文所使用的执行计划可视化工具为 PawSQL Explain Visualizer , 支持MySQL、PostgreSQL、openGauss等数据库。
查询折叠的两种类型
PawSQL优化引擎针对不同的SQL语法结构,支持两种查询折叠的优化策略。其中第一种查询折叠的优化,MySQL 5.7以及PostgreSQL 14.0以上的版本都在优化器内部支持了此类优化;而第二类查询折叠的优化,在最新的MySQL及PostgreSQL版本中都没有支持。
查询折叠类型 I
适用条件
- 在视图本身中,没有distinct关键字
- 在视图中没有聚集函数或窗口函数
- 在视图本身中,没有LIMIT子句
- 在视图本身中,没有UNION或者UNION ALL
- 在外部查询块中,被折叠的视图不是外连接的一部分。
重写策略
将视图拆分并合并到外部查询块中。
案例
- 原始查询
select c.c_name, sum(o_totalprice) price
from customer c, (select o_custkey, o_totalprice from orders where o_shippriority=0)dt
where c.c_custkey = dt.o_custkey
group by c.c_name
- 原始查询的执行计划
- 优化后的查询
select c.c_name, sum(o_totalprice) as price
from customer c, orders
where c.c_custkey = o_custkey and o_shippriority=0
group by c.c_name