如何对PostgreSQL中使用CASE表达式的SQL语句进行调优 ?

以下是一个包含CASE表达式语法的简单SQL语句:

SELECT *
FROM   employee
WHERE 
       CASE
         WHEN emp_salary< 1000
         THEN ‘low’
         WHEN emp_salary>100000
         THEN ‘high’
       END = :a

以下是该SQL语句的查询计划(当绑定变量:a等于’low’时,执行时间为1.01秒)。由于CASE表达式无法利用emp_salary索引,查询需要对EMPLOYEE表进行全表扫描。

我们可以通过使用多个OR条件将CASE表达式重构为以下语法:

select *
  from employee
 where (emp_salary < 1000 and
        ‘low’ = :a or
        ((not (emp_salary < 1000)) or
         emp_salary is null) and
        emp_salary > 100000 and
        ‘high’ = :a)

通过将多个OR条件与AND操作(例如’low’ = :a)结合,可以有效禁用对EMPLOYEE表的不必要数据搜索。

以下是重构后SQL的查询计划(执行速度提升至0.005秒),性能比原始语法快约200倍。新的查询计划显示使用了emp_salary索引的位图索引扫描(Bitmap Index Scan)。

这类SQL重写可以通过Tosska SQL Tuning Expert for PostgreSQL自动完成。实际上,还存在其他性能更优的改写方法,但由于篇幅限制无法在此详述,后续可能会在我的博客中进一步探讨。

Tosska SQL Tuning Expert Pro for PostgreSQL – Tosska Technologies Limited