Max/Min 函数消除规则
根据 select
语句中 max
/min
函数的个数,这一优化规则有以下两种表现形式:
当一个 SQL 满足以下条件时,就会应用这个规则:
- 聚合函数没有相应的
group by
语句。
例如:
select max(a) from (select a from t where a is not null order by a desc limit 1) t
这个新的 SQL 语句在 a
列存在索引(或 a
列是某个联合索引的前缀)时,能够利用索引只扫描一行数据来得到最大或者最小值,从而避免对整个表的扫描。
上述例子最终得到的执行计划如下:
存在多个 max/min 函数时的优化规则
当一个 SQL 满足以下条件时,就会应用这个规则:
- 有多个聚合函数,且所有的聚合函数都是 max/min
- 聚合函数没有相应的
group by
语句。
优化规则会先检查 a
列是否存在索引能够为其保序,如果存在,这个 SQL 会先被重写为两个子查询的笛卡尔积:
这样,两个子句中的 max
/min
函数就可以使用上述“只有一个 max
/min
函数时的优化规则”分别进行优化,最终重写为:
select max_a - min_a
from
(select max(a) as max_a from (select a from t where a is not null order by a desc limit 1) t) t1,
同样的,如果 列能够使用索引保序,那这个优化只会扫描两行数据,避免了对整个表的扫描。但如果 a
列没有可以保序的索引,这个变换会使原本只需一次的全表扫描变成两次,因此这个规则就不会被应用。