15.4. 并行安全性
規劃器把查詢中涉及的操作分類成并行安全、并行受限 或者并行不安全。并行安全的操作不會與并行查詢的使用産生沖突。 并行受限的操作不能在并行工作者中執行,但是能夠在并行查詢的上司者中執行。 是以,并行受限的操作不能出現在
Gather
或
Gather Merge
節點之下, 但是能夠出現在包含有這樣節點的計劃的其他位置。并行不安全的操作不能在并行查詢中執行,甚至不能在上司者中執行。當一個查詢包含任何并行不安全操作時,并行查詢對這個查詢是完全被禁用的。
下面的操作總是并行受限的。
- 公共表表達式(CTE)的掃描。
- 臨時表的掃描。
- 外部表的掃描,除非外部資料包裝器有一個
API。IsForeignScanParallelSafe
- 對
或者相關的InitPlan
的通路。SubPlan
15.4.1. 為函數和聚合加并行标簽
規劃器無法自動判定一個使用者定義的函數或者聚合是并行安全、并行受限還是并行不安全,因為這需要預測函數可能執行的每一個操作。一般而言,這就相當于一個停機問題,是以是不可能的。甚至對于可以做到判定的簡單函數我們也不會嘗試,因為那會非常昂貴而且容易出錯。相反,除非是被标記出來,所有使用者定義的函數都被認為是并行不安全的。在使用
CREATE FUNCTION或者
ALTER FUNCTION時,可以通過指定
PARALLEL SAFE
、
PARALLEL RESTRICTED
PARALLEL UNSAFE
來設定标記 。在使用
CREATE AGGREGATE時,
PARALLEL
選項可以被指定為
SAFE
RESTRICTED
或者
UNSAFE
。
如果函數和聚合會寫資料庫、通路序列、改變事務狀态(即便是臨時改變,例如建立一個
EXCEPTION
塊來捕捉錯誤的 PL/pgSQL)或者對設定做持久化的更改,它們一定要被标記為
PARALLEL UNSAFE
。類似地,如果函數會通路臨時表、用戶端連接配接狀态、遊标、預備語句或者系統無法在工作者之間同步的後端本地狀态,它們必須被标記為
PARALLEL RESTRICTED
。例如,
setseed
和
random
由于後一種原因而是并行受限的。
一般而言,如果一個函數是受限或者不安全的卻被标記為安全,或者它實際是不安全的卻被标記為受限,把它用在并行查詢中時可能會抛出錯誤或者産生錯誤的回答。如果 C 語言函數被錯誤标記,理論上它會展現出完全不明确的行為,因為系統中無法保護自身不受任意 C 代碼的影響。但是,在最有可能的情況下,結果不會比其他任何函數更糟糕。如果有疑慮,最好還是标記函數為
UNSAFE
如果在并行工作者中執行的函數要求上司者沒有持有的鎖,例如讀該查詢中沒有引用的表,那麼工作者退出時會釋放那些鎖(而不是在事務結束時釋放)。如果你寫了一個這樣做的函數并且這種不同的行為對你很重要,把這類函數标記為
PARALLEL RESTRICTED
以確定它們隻在上司者中執行。
注意查詢規劃器不會為了擷取一個更好的計劃而考慮延遲計算并行受限的函數或者聚合。 是以,如果一個被應用到特定表的
WHERE
子句是并行受限的, 查詢規劃器就不會考慮在計劃的并行部分中執行對該表的掃描。 在一些情況中,可以(甚至效率更高)把對表的掃描包括在查詢的并行部分并且延遲對
WHERE
子句的計算,這樣它會出現在
Gather
節點之上。不過,規劃器不會這樣做。
本文轉自PostgreSQL中文社群,原文連結: