Max/Min 函数消除规则

    根据 select 语句中 max/min 函数的个数,这一优化规则有以下两种表现形式:

    当一个 SQL 满足以下条件时,就会应用这个规则:

    • 聚合函数没有相应的 group by 语句。

    例如:

    1. 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 函数时的优化规则”分别进行优化,最终重写为:

    1. select max_a - min_a
    2. from
    3. (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 列没有可以保序的索引,这个变换会使原本只需一次的全表扫描变成两次,因此这个规则就不会被应用。