2017-02-23 50 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只判斷所需要來確定結果的參數;也就是說,不評估第一個非空參數右邊的參數。