postgres COALESCE懒惰吗?

时间:2017-02-23 02:01:10

标签: postgresql coalesce

如果我有这样的查询:

SELECT COALESCE(
  (SELECT value FROM precomputed WHERE ...),
  alwaysComputeValue(...)
);

第二个表达式会被评估吗? 这还取决于执行计划员还是独立的?

2 个答案:

答案 0 :(得分:4)

来自the documentation

  

与CASE表达式类似,COALESCE仅计算确定结果所需的参数;也就是说,不评估第一个非null参数右侧的参数。

答案 1 :(得分:4)

概念上它很懒惰:

  

与CASE表达式类似,COALESCE仅计算确定结果所需的参数;也就是说,不评估第一个非null参数右侧的参数。

https://www.postgresql.org/docs/9.6/static/functions-conditional.html

但是,如果右边的表达式不是易失性的,那么它是否是懒惰的应该没有区别,所以在这种情况下,查询计划者会急切地评估右手参数如果它是稳定的或不可改变的,如果这似乎是一个合理的优化。

一个明显的例子是SELECT COALESCE(a, b) FROM table,它可能会检索所有行的ab字段,而不是检索a然后检索b如果有必要的话。

关于在此获得任何可观察效果的唯一方法是,如果您编写了一个易失性函数并故意将其错误标记为stableimmutable。然后,如果在左侧不为空的coalesce的右侧,则可能进行评估。 (当然,一个功能确实是稳定的,但如果它稳定,它将没有副作用,如果它没有副作用,是否发生它是不可观察的)。

假设:

CREATE OR REPLACE FUNCTION immutable_func(arg integer)
RETURNS integer
AS $BODY$
BEGIN
    RAISE NOTICE 'Immutable function called with %', arg;
    RETURN arg;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;

WITH data AS
(
    SELECT 10 AS num
    UNION ALL SELECT 5
    UNION ALL SELECT 20
)
select coalesce(num, immutable_func(2))
from data

规划器知道每行immutable_func(2)的结果都相同,并且整个查询只调用一次,给我们留言Immutable function called with 2。所以它确实已被评估,即使它不在&#34规则内;第一个非null参数的权利的参数未被评估"。回报是在(合理预期)多个空num的情况下,它仍然只运行一次。

这违反了记录行为的信件,这很好,因为我们已经告诉它这样的优化是有效的。如果这导致了问题,则错误将是标记为IMMUTABLE的功能不在急切的评估中。

它也可以是部分方式。使用SELECT COALESCE(a, Some_Func(b)) FROM table时,它不会急切地评估Some_Func(b),但它会检索b以便能够这样做。

任何时候它实际上影响(非作弊)可观察行为,遵循规则。