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 收集额外的统计信息可以告诉查询规划器对函数的期望。相关:
我有疑问(简体版):
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 收集额外的统计信息可以告诉查询规划器对函数的期望。相关: