谓词下推引起的查询报错
问题现象
计划中出现谓词下推时,按照SQL标准中的查询执行顺序本不应该报错,结果执行出错。
openGauss=# select * from tba;
a
---
-1
2
(2 rows)
openGauss=# select * from tbb;
b
---
-1
1
(2 rows)
openGauss=# select * from tba join tbb on a > b where b > 0 and sqrt(a) > 1;
ERROR: cannot table square root of a negative number
按照SQL执行标准流程: 1、执行FROM子句,能够保证所有数据满足a > b
。 2、执行WHERE子句中b > 0
,若结果为true
则能够推导出a > 0
,并继续执行;若false
则结束,后面的条件被短路,不会执行。 3、执行WHERE子句中sqrt(a) > 1
。
但是实际却报错入参为负值。
原因分析
openGauss=# explain (costs off) select * from tba join tbb on a > b where b > 0 and sqrt(a) > 1;
QUERY PLAN
----------------------------------
Nest loop
Join Filter: (a > b)
-> Seq Scan on public.tba
Filter: (sqrt(a) > 1)
-> Materialize
-> Seq Scan on public.tbb
Filter: (b > 0)
(7 rows)
分析计划可知,原本a > b
, b > 0
, sqrt(a) > 1
的三个条件,被拆分下推到了不同的算子之中,从而并非按顺序执行. 且当前的等价类推理仅支持等号推理,因此无法自动推理补充出a > 0
。 最终查询报错。
处理办法
谓词下推可以极大的提升查询性能,且此种短路、推导的特殊场景,在大多数数据库优化器下都没有过多考虑,因此建议修改查询语句,在相关的条件下手动添加a > 0
。
openGauss=# select * from tba join tbb on a > b where b > 0 and a > 0 and sqrt(a) > 1;
a | b
---+---
2 | 1
(1 row)
openGauss=# explain (costs off) select * from tba join tbb on a > b where b > 0 and a > 0 and sqrt(a) > 1;
QUERY PLAN
--------------------------------------
Nest loop
Join Filter: (a > b)
-> Seq Scan on public.tba
Filter: (a > 0 and sqrt(a) > 1)
-> Materialize
-> Seq Scan on public.tbb
Filter: (b > 0)
(7 rows)