2017-02-23 61 views
6

如果我有这样的查询:postgres COALESCE是否懒惰?

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

将在第二公式进行计算? 这也取决于执行计划者或它是独立的吗?

+4

好问题。我会说:检查计划。 – wildplasser

回答

4
概念

它是懒:

等的情况下表达,COALESCE只判断所需要来确定结果的参数;也就是说,不评估第一个非空参数右边的参数。

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

但是,如果表达的权利是不挥发的话,应该没有什么区别它是否是懒还是没有,所以在这种情况下,这将是允许的查询规划热切如果它是稳定的或不可变的,则评估右边的论点,如果这看起来是一个明智的优化。

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

关于在这里产生任何可观察效果的唯一方法是,如果您编写了易失性函数并故意将其错误标记为stableimmutable。那么它将是可能的它将被评估,如果在右边的​​3210左手不为空。 (对于一个确实稳定的函数,当然也是可能的,但是如果它是稳定的,那么它就没有副作用,如果没有副作用,它是否会发生也不会被观察到)。

考虑:

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。所以它的确已经过评估,即使它不在“第一个非空参数的权利参数未被评估”的规则之内。这个回报就是在多个无效的(合理预期)情况下,它仍然只能运行一次。

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

它也可以是部分路径。与SELECT COALESCE(a, Some_Func(b)) FROM table它不会热切地评估Some_Func(b),但它将检索b能够这样做。

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

+0

哇,这么长时间的答案,但是..我知道它可以评估*在理论上*如果我标记函数不变或稳定,并设置它为规划师低成本,*但*这*真的*发生? :-) – langpavel

+0

是的,它可以。将更新答案。 –

4

the documentation

等的情况下表达,COALESCE只判断所需要来确定结果的参数;也就是说,不评估第一个非空参数右边的参数。