postgres COALESCE 是懒惰的吗?

问题描述 投票:0回答:3

如果我有这样的查询:

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

第二个表达式会被计算吗? 这也可以取决于执行计划器还是独立的?

postgresql coalesce
3个回答
10
投票

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

与 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
以便能够这样做。

只要它实际影响(非作弊)可观察行为,就遵循该规则。


4
投票

来自文档

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


0
投票

它与“coagulate”这个词相似吗?如果是这样,那么也许可以将某种程度的负面含义归因于诸如“合并”、“联盟”等词。?

© www.soinside.com 2019 - 2024. All rights reserved.