谓词下推引起的查询报错

问题现象

计划中出现谓词下推时,按照SQL标准中的查询执行顺序本不应该报错,结果执行出错。

  1. openGauss=# select * from tba;
  2. a
  3. ---
  4. -1
  5. 2
  6. (2 rows)
  7. openGauss=# select * from tbb;
  8. b
  9. ---
  10. -1
  11. 1
  12. (2 rows)
  13. openGauss=# select * from tba join tbb on a > b where b > 0 and sqrt(a) > 1;
  14. 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

但是实际却报错入参为负值。

原因分析

  1. openGauss=# explain (costs off) select * from tba join tbb on a > b where b > 0 and sqrt(a) > 1;
  2. QUERY PLAN
  3. ----------------------------------
  4. Nest loop
  5. Join Filter: (a > b)
  6. -> Seq Scan on public.tba
  7. Filter: (sqrt(a) > 1)
  8. -> Materialize
  9. -> Seq Scan on public.tbb
  10. Filter: (b > 0)
  11. (7 rows)

分析计划可知,原本a > b, b > 0, sqrt(a) > 1的三个条件,被拆分下推到了不同的算子之中,从而并非按顺序执行. 且当前的等价类推理仅支持等号推理,因此无法自动推理补充出a > 0。 最终查询报错。

处理办法

谓词下推可以极大的提升查询性能,且此种短路、推导的特殊场景,在大多数数据库优化器下都没有过多考虑,因此建议修改查询语句,在相关的条件下手动添加a > 0

  1. openGauss=# select * from tba join tbb on a > b where b > 0 and a > 0 and sqrt(a) > 1;
  2. a | b
  3. ---+---
  4. 2 | 1
  5. (1 row)
  6. openGauss=# explain (costs off) select * from tba join tbb on a > b where b > 0 and a > 0 and sqrt(a) > 1;
  7. QUERY PLAN
  8. --------------------------------------
  9. Nest loop
  10. Join Filter: (a > b)
  11. -> Seq Scan on public.tba
  12. Filter: (a > 0 and sqrt(a) > 1)
  13. -> Materialize
  14. -> Seq Scan on public.tbb
  15. Filter: (b > 0)
  16. (7 rows)