PostgresQL:在 WHERE 中使用 CASE 的性能
PostgresSQL: Performance of using CASE inside WHERE
使用 PostgreSQL,我需要定义一个查询,该查询将根据参数有条件地 SELECT
某些数据。在此语句中,我有一个条件,仅当另一个条件的计算结果为 TRUE
.
时才需要计算
为了解决这个问题,我的第一个想法是在 WHERE
中使用 CASE
,效果很好。例如,使用具有列 id
、name
和 value
:
的 table test_table
SELECT
name
FROM test_table
WHERE
CASE
WHEN > 10 THEN test_table.value >
ELSE TRUE
END
;
但是,其他同行建议改用常规布尔逻辑,因为它会执行得更快。例如:
SELECT
name
FROM test_table
WHERE
(
<= 10
OR test_table.value >
)
;
在测试了大约 10 万行并使用 EXPLAIN ANALYSE
后,速度差异似乎平均约为 1 毫秒:
- 使用
CASE
:~19.5 毫秒执行时间
- 使用常规布尔值:~18.5ms 执行时间
问题是:第二种方法真的更快吗?或者是我的测试有缺陷,因此结果不正确?
并不是说不使用 case
总是更快。问题是 case
阻止优化器选择不同的执行路径。它基本上是说条件 有 要按顺序执行,因为 case
表达式强加顺序。
选项越少,生成的查询计划可能会越慢。
有些情况下执行顺序是优势。当您知道某些条件的评估成本非常高时尤其如此,因此您希望确保首先评估其他条件:
where (case when x = 1 then true
when <some expensive function> then true
end)
可能比:
更高效
where (x = 1) or <some expensive function>
(尽管在这个简单的示例中,我希望 Postgres 编译器足够聪明,能够在第二种情况下做正确的事情)。
避免在 where
子句中使用 case
的第二个原因是美观。已经有足够的布尔运算符来生成您需要的几乎任何条件——所以 case
是语法糖,通常不提供额外的营养
使用 PostgreSQL,我需要定义一个查询,该查询将根据参数有条件地 SELECT
某些数据。在此语句中,我有一个条件,仅当另一个条件的计算结果为 TRUE
.
为了解决这个问题,我的第一个想法是在 WHERE
中使用 CASE
,效果很好。例如,使用具有列 id
、name
和 value
:
test_table
SELECT
name
FROM test_table
WHERE
CASE
WHEN > 10 THEN test_table.value >
ELSE TRUE
END
;
但是,其他同行建议改用常规布尔逻辑,因为它会执行得更快。例如:
SELECT
name
FROM test_table
WHERE
(
<= 10
OR test_table.value >
)
;
在测试了大约 10 万行并使用 EXPLAIN ANALYSE
后,速度差异似乎平均约为 1 毫秒:
- 使用
CASE
:~19.5 毫秒执行时间 - 使用常规布尔值:~18.5ms 执行时间
问题是:第二种方法真的更快吗?或者是我的测试有缺陷,因此结果不正确?
并不是说不使用 case
总是更快。问题是 case
阻止优化器选择不同的执行路径。它基本上是说条件 有 要按顺序执行,因为 case
表达式强加顺序。
选项越少,生成的查询计划可能会越慢。
有些情况下执行顺序是优势。当您知道某些条件的评估成本非常高时尤其如此,因此您希望确保首先评估其他条件:
where (case when x = 1 then true
when <some expensive function> then true
end)
可能比:
更高效where (x = 1) or <some expensive function>
(尽管在这个简单的示例中,我希望 Postgres 编译器足够聪明,能够在第二种情况下做正确的事情)。
避免在 where
子句中使用 case
的第二个原因是美观。已经有足够的布尔运算符来生成您需要的几乎任何条件——所以 case
是语法糖,通常不提供额外的营养