高级SQL优化之HAVING条件下推

2024-08-20 15:20:47 浏览数 (3)

本篇属于高级SQL优化专题中的一篇,高级SQL优化系列专题介绍PawSQL优化引擎以及Oracle等数据库查询优化算法原理及优化案例,欢迎大家订阅。

本文所使用的执行计划可视化工具为 PawSQL Explain Visualizer , 支持MySQL、PostgreSQL、openGauss、Oracle等数据库。

问题定义

HAVING条件下推是指将符合条件的HAVING子句中的过滤谓词下推至同一个查询块中的WHERE子句,从而提升查询效率的重写优化算法。

从逻辑上,HAVING条件是在分组之后执行的,而WHERE子句上的条件可以在表访问的时候(索引访问),或是表访问之后、分组之前执行,这两种都比方式都在分组之前进行了过滤操作,降低了分组的数据集大小,所以执行代价要小。

考虑下面的例子,

代码语言:javascript复制
select o_custkey, count(*) from orders group by o_custkey having o_custkey < 100

重写后的SQL为,

代码语言:javascript复制
select o_custkey, count(*) from orders where o_custkey < 100 group by o_custkey

适用条件

  1. 候选条件是单独的HAVING子句或是由AND连接的条件
  2. 候选条件中引用的变量不是聚集函数或是窗口函数

性能验证

1. 改写前的执行计划

从执行计划可以看到,HAVING子句的条件o_custkey < 100是在分组聚集运算后进行运算的,导致分组前无法进行过滤,所以分组运算处理36042行,执行时间达237.49ms。

2. 改写后的执行计划

通过将HAVING子句的条件o_custkey < 100下推至WHERE子句,使得后续的分组聚集运算行数大大减少;同时可以利用在o_custkey列上的索引,整体的执行时间也降低到1.36ms.

3* 优化过程解析

通过将HAVING子句的条件o_custkey < 100下推至WHERE子句,提前过滤,使得后续的分组运算的行数大大减少(36042 vs. 2742);同时可以利用在o_custkey列上的索引进行覆盖索引顺序扫描,整体的执行时间从237.49ms降低到1.36ms性能提升了170多倍

4. 数据库优化器对HAVING条件下推的支持

  • PostgreSQL优化器
  • Oracle优化器

我们可以看到,MySQL、PostgreSQL、Oracle数据库的优化器都没有对HAVING条件下推重写优化的支持。

PawSQL对HAVING条件下推的支持

  • 自动优化:PawSQL针对所有数据库默认开启此优化,而且可以基于重写后的SQL进行索引推荐(如果没有最优索引的话),以上的SQL通过PawSQL的优化结果如下。

  • PawSQL提供优化前后的执行计划对比。
  • 启用设置:用户可以在自己的默认优化设置或是定义每个优化任务的时候自主启用或禁用该选项。

关于PawSQL

PawSQL专注数据库性能优化的自动化和智能化,支持MySQL,PostgreSQL,Opengauss等,提供的SQL优化产品包括

  • PawSQL Cloud,在线自动化SQL优化工具,支持SQL审查,智能查询重写、基于代价的索引推荐,适用于数据库管理员及数据应用开发人员,
  • PawSQL Advisor,IntelliJ 插件, 适用于数据应用开发人员,可以IDEA/DataGrip应用市场通过名称搜索“PawSQL Advisor”安装。
  • PawSQL Engine, 是PawSQL系列产品的后端优化引擎,可以以docker镜像的方式独立安装部署,并通过http/json的接口提供SQL优化服务。

0 人点赞