【问题标题】:Postgres SQL - strange performance issue in selectPostgresql - 选择中的奇怪性能问题
【发布时间】:2019-09-24 20:56:37
【问题描述】:

我有查询(简化版):

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 也一样 - 也超级快。

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

对此感到非常惊讶......有人可以解释一下为什么吗?

【问题讨论】:

  • 这是一个函数。规划者不知道会发生什么。
  • 好的,同意 - 但是这对 foo = 4 与 foo > 2 有何影响,在这两种情况下它都不知道。
  • 这个问题对于实际的函数和表定义、您的 Postgres 版本以及实际的查询计划会更有用。

标签: sql postgresql performance indexing postgresql-performance


【解决方案1】:

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

谓词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 收集额外的统计信息,告诉查询计划者应该做什么从函数中期待。相关:

【讨论】:

  • 谢谢 - 有道理。我不能发布确切的功能它太复杂了。它是稳定的并且接收更多参数,所以我不能真正使用表达式索引。我想知道我是否会返回带有 3 个值而不是 INTEGER 的 ENUM - 会有帮助吗?
猜你喜欢
  • 2015-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 1970-01-01
相关资源
最近更新 更多