谓词推导(条件下推增强)

PolarDB支持谓词推导,即通过深入分析现有SQL查询中的谓词条件,能够有效地提取并推导出新的谓词。这一过程不仅局限于等值关系的解析,也包括非等值关系的推导。通过这一机制,PolarDB能够生成更具针对性的谓词条件,从而为查询优化器提供更有效的信息。在查询优化的过程中,谓词的有效性直接影响到优化器在选择索引和确定连接顺序等关键决策时的表现。通过推导出的新谓词,优化器可以在搜索执行计划时考虑到更多的可能性,进而提高查询性能。

版本限制

适用的数据库引擎版本为MySQL 8.0.2,且小版本需为8.0.2.2.23及以上版本。如何查看内核版本,请参见查询版本号

使用场景

在谓词下推(条件下推)的过程中,PolarDB通过谓词推导的方式增强其优化能力。谓词下推包括但不限于以下几种实现方式:

说明

谓词推导的主要目标是生成尽可能多的单表条件,而不是为了排列组合推导出任意两个变量之间的关系。通过谓词推导,系统能够识别并生成新的、有效的过滤条件,这些条件可以在后续的优化阶段中用于进一步缩小数据集,从而提高查询性能和效率。这一过程不仅增强了PolarDB在谓词下推方面的能力,还确保了查询优化器能够更智能地处理复杂的查询逻辑,最终提升系统的整体性能。

主要包括以下场景:

  • 非等值/等值简单谓词推导,示例如下:

    -- 原SQL
    SELECT * FROM t1, v1 WHERE v1.a > t1.a AND t1.a > 1
    -- 推导后的SQL
    SELECT * FROM t1, v1 WHERE v1.a > t1.a AND t1.a > 1 AND v1.a > 1
    
    -- 原SQL
    SELECT * FROM t1, v1 WHERE v1.b < t1.c AND t1.c < t2.c AND t2.c = 1;
    -- 推导后的SQL
    SELECT * FROM t1, v1 WHERE v1.b < t1.c AND t1.c < t2.c AND t2.c = 1 AND v1.b < 1 AND t1.c < 1;
  • 对于符合交换律的表达式,也可以参与谓词推导,示例如下:

    -- 原SQL
    SELECT * FROM t1, v2 WHERE v2.c1 < t1.c2 + t1.c1 AND t1.c1 + t1.c2 < 2;
    -- 推导后的SQL
    SELECT * FROM t1, v2 WHERE v2.c1 < t1.c2 + t1.c1 AND t1.c1 + t1.c2 < 2 AND v2.c1 < 2;
  • 基于等值关系的复杂谓词推导,示例如下:

    -- 原SQL
    SELECT * FROM t3, v3 WHERE v3.c2 = t3.c2 AND t3.c2 LIKE "%00%";
    -- 推导后的SQL
    SELECT * FROM t3, v3 WHERE v3.c2 = t3.c2 AND t3.c2 LIKE "%00%" AND v3.c2 LIKE "%00%";
    
    -- 原SQL
    SELECT * FROM t1, v2 WHERE v2.c1 = t1.c2 AND t1.c2 IN (1,5,7);
    -- 推导后的SQL
    SELECT * FROM t1, v2 WHERE v2.c1 = t1.c2 AND t1.c2 IN (1,5,7) AND  v2.c1 IN (1,5,7);
  • HAVING中MIN/MAX推导,示例如下:

    -- 原SQL
    SELECT * FROM t1 GROUP BY a,b,c HAVING MAX(b) > 20;
    -- 推导后的SQL
    SELECT * FROM t1 WHERE b > 20 GROUP BY a,b,c;
    
    -- 原SQL
    SELECT * FROM t1 GROUP BY a,b,c HAVING MIN(b) < 20;
    -- 推导后的SQL
    SELECT * FROM t1 WHERE b < 20 GROUP BY a,b,c;

使用限制

  • 在整个谓词推导过程中,只有在满足相同比较类型条件的前提下,才能将这些谓词统一进行推导,示例如下:

    CREATE TABLE t1(c1 INT, c2 INT);
    CREATE TABLE t2(c1 INT, c2 VARCHAR(64));
    CREATE view v2 AS SELECT * FROM t2;
    SELECT * FROM v2,t1 WHERE v2.c1 > t1.c2 AND t1.c2 > v2.c2;
    说明

    示例SQL中v2.c2VARCHAR类型,虽然看起来可以通过中间变量t1.c2传递非等值关系,但由于v2.c1INT类型,v2.c2VARCHAR类型,t1.c2作为INT类型,在分别跟v2.c1v2.c2比较时是用不同类型的取值方式,因此强行推导之后是不符合SQL原始语义的。

  • MIN/MAX函数的推导仅适用于SQL查询中存在且仅存在单一的MIN/MAX聚合函数的情况。如果查询中包含其他类似的聚合函数,则在WHERE子句中推导出的谓词条件可能会影响这些其他聚合函数的计算结果,从而导致推导后的SQL与原始SQL之间出现不等价的情况。示例如下:

    SELECT a, MIN(b), AVG(c) FROM t1 GROUP BY a HAVING MIN(b) < 20;
    说明

    示例SQL中存在两个聚合函数,分别是AVG(c)MIN(b),若按规则推导b < 20WHERE从句上,在表t1扫描过程中会过滤掉不满足b < 20的行,这些被过滤掉的数据就不会对AVG(c)的值产生影响,因此对于某个分组来说,必然会影响AVG(c)值,查询结果与原始语义不符,所以这种会影响其他聚合函数结果的情况并不支持MIN/MAX推导。

使用方法

准备工作

在使用该条件下推之前,您需要配置loose_predicate_deduce_mode参数来开启谓词推导功能。具体操作请参见设置集群参数和节点参数

参数名称

级别

描述

loose_predicate_deduce_mode

Global

谓词推导功能控制开关。取值范围如下:

  • REPLICA_ON(默认值):仅在只读节点开启谓词推导功能。

  • ON:开启谓词推导功能。

  • OFF:关闭谓词推导功能。

说明

MIN/MAX的推导没有单独的参数开启,您可以通过设置loose_having_cond_pushdown_mode开启条件下推(HAVING子句下推至WHERE子句)功能,MIN/MAX的推导功能也会随之开启。更多信息,请参见条件下推(HAVING to WHERE)

示例1

-- 创建示例用表
CREATE VIEW v1
AS
SELECT c1, c2, MAX(c3) AS max_c3
    , AVG(c4) AS avg_c4
FROM t2
GROUP BY c1, c2
HAVING max_c3 > 10;

EXPLAIN FORMAT = TREE SELECT * FROM v1, t1 WHERE v1.c1 >= t1.c2 AND t1.c2 = v1.c2;

EXPLAIN
-> Inner hash join (t1.c2 = v1.c2)
    -> Table scan on t1  (cost=0.18 rows=10)
    -> Hash
        -> Table scan on v1
            -> Materialize
                -> Filter: (max_c3 > 10)
                    -> Table scan on <temporary>
                        -> Aggregate using temporary table
                            -> Filter: (t2.c1 >= t2.c2)  (cost=0.75 rows=2)
                                -> Table scan on t2  (cost=0.75 rows=5)
说明

条件下推(WHERE条件下推派生表)之前增加谓词推导的流程,v1.c1 >= t1.c2 and t1.c2 = v1.c2通过非等值和等值关系的传递,可以得到单表条件v1.c1 > v1.c2,进而通过条件下推,将v1.c1 > v1.c2条件下压到派生表中,转换成派生表中对应的字段t2.c1 >= t2.c2实现提前过滤数据。

示例2

SELECT a, b, ee
FROM (
    SELECT b, a, MIN(c) AS ee
    FROM t1
    GROUP BY a, b
) dt
GROUP BY a, b
HAVING MIN(ee) < 20;

-- 推导变换后========>
SELECT a, b, ee
FROM (
    SELECT b, a, MIN(c) AS ee
    FROM t1
  WHERE c < 20
    GROUP BY a, b
) dt
GROUP BY a, b;


-- 通过下面的查询计划也能看出应用MIN/MAX推导之后的结果
EXPLAIN FORMAT = TREE SELECT a, b, ee
FROM (
    SELECT b, a, MIN(c) AS ee
    FROM t1
    GROUP BY a, b
) dt
GROUP BY a, b
HAVING MIN(ee) < 20;

EXPLAIN
-> Table scan on <temporary>
    -> Aggregate using temporary table
        -> Table scan on dt
            -> Materialize
                -> Table scan on <temporary>
                    -> Aggregate using temporary table
                        -> Filter: (t1.c < 20)  (cost=*** rows=***)
                            -> Table scan on t1  (cost=*** rows=***)
说明

其中外层查询的MIN(ee) < 20首先通过MIN/MAX推导出dt.ee < 20条件下推到派生表dt之后,作为派生表内部的HAVING条件 MIN(c) < 20 进一步通过MIN/MAX推导出 t1.c < 20, 在一系列变换后,过滤条件更靠近数据源,起到加速查询的效果。