postgres COALESCE懒惰吗?

lan*_*vel 6 postgresql coalesce

如果我有这样的查询:

SELECT COALESCE(
  (SELECT value FROM precomputed WHERE ...),
  alwaysComputeValue(...)
);
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*nna 6

从概念上讲,它是懒惰的:

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

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

然而,如果右边的表达式不是 volatile 那么它是否是惰性的应该没有区别,所以在这种情况下,查询规划器可以热切地评估右边的参数,如果它是稳定的或不可变,如果这看起来是一个明智的优化。

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

关于在这里产生任何可观察效果的唯一方法是,如果您编写了一个 volatile 函数并故意错误地将其标记为stableor immutable。那么这将是可能为它是如果的右手评估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
Run Code Online (Sandbox Code Playgroud)

规划器知道它对immutable_func(2)每一行都有相同的结果,并在整个查询中调用它一次,给我们消息Immutable function called with 2。所以它确实被评估了,即使它不在“第一个非空参数右侧的参数不被评估”的规则内。回报是在(合理预期)多个 null 的情况下,num它仍然只会运行一次。

这与所记录的行为背道而驰是可以的,因为我们已经告诉它这样的优化是有效的。如果这引起了问题,则错误在于将函数标记为IMMUTABLE不在急切评估中。

它也可以是半途而废。有了SELECT COALESCE(a, Some_Func(b)) FROM table它,它不会Some_Func(b)急切地评估,但它会检索b到能够这样做。

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


kli*_*lin 5

文档中:

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