Postgres SQL - select 中的奇怪性能问题

Postgres SQL - strange performance issue in select

我有疑问(简体版):

WITH temp AS (SELECT id, foo(id) AS foo FROM test)
SELECT id FROM temp WHERE foo = 4;

foo(id) 是 returns 0、2 或 4(仅这些值)

的函数

以上 ... WHERE foo = 4 的查询需要几分钟,但令人惊讶的是,当我更改为 ... WHERE foo != 0 AND foo != 2 时,查询性能是毫秒。

如果我这样做也一样 ... WHERE foo > 2 - 也超级快。

我检查了执行计划,但没有发现任何差异。

对此感到非常惊讶...有人可以解释一下原因吗?

假设函数 foo() 不能被内联,Postgres 不知道它可能是什么 return,所以它必须假设任何数字都同样常见。

谓词 foo = 4 告诉 Postgres 期望 next to no row 符合条件。

谓词 foo != 0 AND foo != 2,OTOH,告诉 Postgres 期望 几乎所有行 符合条件。使用 foo > 2 它仍然是所有行的一半左右。

这通常会导致不同的查询计划,第一个似乎表现不佳,而其他的似乎表现不错。

细节被缺失的信息隐藏了。但这就是重点。

如果函数是 IMMUTABLE,您可以在 foo(foo(id)) 上创建表达式索引。假设 3 个可能的值是均匀分布的,该索引本身可能是无用的。 (也许 对多列索引 foo(foo(id), id) 的仅索引扫描会有所帮助,如果该函数是昂贵的并且声明为这样的话。)但是它使 Postgres 收集额外的统计信息可以告诉查询规划器对函数的期望。相关: