PolarDB支持谓词推导,即通过深入分析现有SQL查询中的谓词条件,能够有效地提取并推导出新的谓词。这一过程不仅局限于等值关系的解析,也包括非等值关系的推导。通过这一机制,PolarDB能够生成更具针对性的谓词条件,从而为查询优化器提供更有效的信息。在查询优化的过程中,谓词的有效性直接影响到优化器在选择索引和确定连接顺序等关键决策时的表现。通过推导出的新谓词,优化器可以在搜索执行计划时考虑到更多的可能性,进而提高查询性能。
版本限制
适用的数据库引擎版本为MySQL 8.0.2,且小版本需为8.0.2.2.23及以上版本。如何查看内核版本,请参见查询版本号。
使用场景
在谓词下推(条件下推)的过程中,PolarDB通过谓词推导的方式增强其优化能力。谓词下推包括但不限于以下几种实现方式:
HAVING
下推至WHERE
的条件下推:将可以在聚合前应用的HAVING
条件转换为WHERE
条件,以减少参与聚合的数据量。更多信息,请参见条件下推(HAVING to WHERE)。WHERE
条件下推至派生表:将外部查询的WHERE
条件下推到派生表中,以便更早地过滤数据。更多信息,请参见条件下推(WHERE条件下推派生表)。WHERE
子句下推至IN
子查询:将外部查询的WHERE
条件下推到IN
子查询中,提高子查询的执行效率。更多信息,请参见条件下推(WHERE子句下推至IN子查询)。连接条件下推至物化派生表:将连接条件直接应用于物化派生表,以减少不必要的数据扫描。更多信息,请参见条件下推(连接条件下推至物化派生表)。
谓词推导的主要目标是生成尽可能多的单表条件,而不是为了排列组合推导出任意两个变量之间的关系。通过谓词推导,系统能够识别并生成新的、有效的过滤条件,这些条件可以在后续的优化阶段中用于进一步缩小数据集,从而提高查询性能和效率。这一过程不仅增强了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.c2
是VARCHAR
类型,虽然看起来可以通过中间变量t1.c2
传递非等值关系,但由于v2.c1
是INT
类型,v2.c2
是VARCHAR
类型,t1.c2
作为INT
类型,在分别跟v2.c1
和v2.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 < 20
至WHERE
从句上,在表t1
扫描过程中会过滤掉不满足b < 20
的行,这些被过滤掉的数据就不会对AVG(c)
的值产生影响,因此对于某个分组来说,必然会影响AVG(c)
值,查询结果与原始语义不符,所以这种会影响其他聚合函数结果的情况并不支持MIN/MAX
推导。
使用方法
准备工作
在使用该条件下推之前,您需要配置loose_predicate_deduce_mode
参数来开启谓词推导功能。具体操作请参见设置集群参数和节点参数。
参数名称 | 级别 | 描述 |
loose_predicate_deduce_mode | Global | 谓词推导功能控制开关。取值范围如下:
|
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
, 在一系列变换后,过滤条件更靠近数据源,起到加速查询的效果。