Postgres SQL-选择中出现奇怪的性能问题

时间:2019-09-24 20:56:37

标签: sql postgresql performance indexing postgresql-performance

我有查询(简体版):

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

foo(id)是返回0、2或4(仅这些值)的函数

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

就算我... WHERE foo > 2也一样-速度也很快。

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

对此感到非常惊讶……有人可以向我解释原因吗?

1 个答案:

答案 0 :(得分:1)

假设函数foo()不能被内联,Postgres不知道它可能返回什么,因此必须假定任何数字都是相同的。

谓词foo = 4告诉Postgres期望无行旁边将符合条件。

谓词foo != 0 AND foo != 2(OTOH)告诉Postgres期望几乎所有行合格。使用foo > 2,它仍然占所有行的一半。

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

由于缺少信息而隐藏了详细信息。但这就是重点。

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