如果我有这样的查询:
SELECT COALESCE(
(SELECT value FROM precomputed WHERE ...),
alwaysComputeValue(...)
);
第二个表达式会被计算吗? 这也可以取决于执行计划器还是独立的?
从概念上讲,它是懒惰的:
与 CASE 表达式一样,COALESCE 仅计算确定结果所需的参数;也就是说,第一个非空参数右侧的参数不会被求值。
https://www.postgresql.org/docs/9.6/static/functions-conditional.html
但是,如果右侧的表达式不是易失性的,那么它是否是惰性的应该没有什么区别,因此在这种情况下,如果右侧参数是稳定的,则允许查询规划器急切地评估右侧参数或者不可变,如果这看起来是一个明智的优化。
一个明显的情况是,使用
SELECT COALESCE(a, b) FROM table
,它可能会检索所有行的 a
和 b
字段,而不是先检索 a
,然后在必要时检索 b
。
在这里产生任何可观察到的效果的唯一方法是,如果您编写了一个易失性函数并故意将其错误标记为
stable
或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
规划器知道每行都会有相同的
immutable_func(2)
结果,并在整个查询中调用它一次,给我们消息 Immutable function called with 2
。因此,它确实已被评估,即使它不符合“第一个非空参数右侧的参数不被评估”的规则。回报是,在(合理预期)多个 null num
的情况下,它仍然只会运行一次。
这与记录的行为的字面意思相悖是可以的,因为我们已经告诉它这样的优化是有效的。如果这导致了问题,则错误将在于将函数标记为
IMMUTABLE
,而不是在急切的评估中。
也可以是中途的。使用
SELECT COALESCE(a, Some_Func(b)) FROM table
,它不会急切地评估 Some_Func(b)
,但它会检索 b
以便能够这样做。
只要它实际影响(非作弊)可观察行为,就遵循该规则。
来自文档:
与 CASE 表达式一样,COALESCE 仅计算确定结果所需的参数;也就是说,不计算第一个非空参数右侧的参数。
它与“coagulate”这个词相似吗?如果是这样,那么也许可以将某种程度的负面含义归因于诸如“合并”、“联盟”等词。?