支援版本:目前 (16) / 15 / 14 / 13 / 12
開發版本:devel
不支援版本:11 / 10 / 9.6

15.3. 平行計畫 #

由於每個工作執行計畫的平行部分直到完成,因此無法僅採用一般查詢計畫並使用多個工作執行。每個工作會產生輸出結果集的完整副本,因此查詢執行的速度不會比正常情況快,但會產生不正確的結果。相反地,計畫的平行部分必須是查詢最佳化器內部所知的部分計畫;亦即,必須建構計畫,以便執行計畫的每個程序只會產生輸出列的子集,且每個必要的輸出列保證只會由一個協力程序產生。通常,這表示查詢驅動表的掃描必須是平行感知掃描。

15.3.1. 平行掃描 #

目前支援下列類型的平行感知表格掃描。

  • 平行順序掃描 中,表格區塊會分成範圍,並在合作處理程序之間共用。每個工作程序會在要求額外的區塊範圍之前,完成其給定區塊範圍的掃描。

  • 平行位元圖堆積掃描 中,會選取一個處理程序作為引導。該處理程序會掃描一個或多個索引,並建立一個位元圖,指出需要拜訪哪些表格區塊。這些區塊接著會像平行順序掃描一樣,在合作處理程序之間分配。換句話說,堆積掃描會平行執行,但基礎索引掃描則不會。

  • 平行索引掃描平行僅索引掃描 中,合作處理程序會輪流從索引讀取資料。目前,平行索引掃描僅支援 btree 索引。每個處理程序會宣告一個單一索引區塊,並掃描和傳回該區塊引用的所有元組;其他處理程序可以同時從不同的索引區塊傳回元組。平行 btree 掃描的結果會在每個工作程序中以排序順序傳回。

其他掃描類型,例如非 btree 索引的掃描,未來可能會支援平行掃描。

15.3.2. 平行聯結 #

就像在非平行計畫中一樣,驅動表格可能會使用巢狀迴圈、雜湊聯結或合併聯結,聯結到一個或多個其他表格。聯結的內側可能是任何類型的非平行計畫,只要在平行工作程序中執行時安全,就受到計畫器的支援。根據聯結類型,內側也可能是平行計畫。

  • 巢狀迴圈聯結 中,內側永遠是非平行的。儘管它會完整執行,但如果內側是索引掃描,這會很有效率,因為外部元組以及在索引中查詢值的迴圈會在合作處理程序之間分配。

  • 合併聯結 中,內側永遠是非平行計畫,因此會完整執行。這可能會很沒效率,特別是如果必須執行排序,因為工作和結果資料會在每個合作處理程序中重複。

  • 雜湊聯結(沒有「平行」前綴)中,內側由每個合作程序完全執行,以建立雜湊表的相同副本。如果雜湊表很大或計畫很昂貴,這可能會很低效。在 平行雜湊聯結 中,內側是 平行雜湊,它將建立共享雜湊表的工作分派給合作程序。

15.3.3. 平行聚合 #

PostgreSQL 透過兩階段聚合來支援平行聚合。首先,參與查詢平行部分的每個程序執行聚合步驟,為每個程序所知的每個群組產生部分結果。這在計畫中反映為 Partial Aggregate 節點。其次,部分結果透過 GatherGather Merge 傳輸給領導者。最後,領導者在所有工作程序中重新聚合結果,以產生最終結果。這在計畫中反映為 Finalize Aggregate 節點。

由於 Finalize Aggregate 節點在領導程序上執行,因此與輸入列數相比,產生相對大量群組的查詢將顯得對查詢規劃器較不理想。例如,在最壞的情況下,Finalize Aggregate 節點看到的群組數目可能與 Partial Aggregate 階段中所有工作程序看到的輸入列數一樣多。對於這種情況,顯然使用平行聚合不會有性能優勢。查詢規劃器在規劃過程中會考慮到這一點,並且不太可能在此情況下選擇平行聚合。

平行聚合並非在所有情況下都受支援。每個聚合都必須 安全 以進行平行處理,並且必須具有組合函數。如果聚合具有類型為 internal 的轉換狀態,則它必須具有序列化和反序列化函數。有關更多詳細資訊,請參閱 建立聚合。如果任何聚合函數呼叫包含 DISTINCTORDER BY 子句,則不支援平行聚合,也不支援已排序的集合聚合或查詢涉及 GROUPING SETS 的情況。只有當查詢中涉及的所有聯結也是計畫的平行部分時,才能使用它。

15.3.4. 平行追加 #

每當 PostgreSQL 需要將來自多個來源的列組合成單一結果集時,它會使用 AppendMergeAppend 計畫節點。在實作 UNION ALL 或掃描分割表時,通常會發生這種情況。此類節點可以用於平行計畫,就像它們可以用於任何其他計畫一樣。然而,在平行計畫中,規劃器可能會改用 Parallel Append 節點。

當在平行計畫中使用 Append 節點時,每個程序會按照出現順序執行子計畫,讓所有參與的程序合作執行第一個子計畫,直到它完成,然後在差不多同一時間移至第二個計畫。改用 Parallel Append 時,執行器會盡可能平均地將參與的程序分散到其子計畫,讓多個子計畫同時執行。這可避免競爭,並避免在從未執行子計畫的程序中支付子計畫的啟動成本。

此外,與只能在平行計畫中使用時有部分子項的常規 Append 節點不同,Parallel Append 節點可以有部分和非部分子計畫。非部分子項只會由單一程序掃描,因為掃描它們超過一次會產生重複的結果。因此,涉及附加多個結果集的計畫即使在無法使用有效的部分計畫時,也能達成粗略的平行處理。例如,考慮針對分區表的查詢,只能透過使用不支援平行掃描的索引來有效實作。規劃器可能會選擇常規 Index Scan 計畫的 Parallel Append;每個個別索引掃描都必須由單一程序執行到完成,但不同的掃描可以由不同的程序同時執行。

enable_parallel_append 可用於停用此功能。

15.3.5. 平行計畫提示 #

如果預期會執行平行計畫的查詢未產生平行計畫,您可以嘗試降低 parallel_setup_costparallel_tuple_cost。當然,此計畫可能會比規劃器偏好的串行計畫慢,但並非總是如此。即使將這些設定設為非常小的值(例如,將它們都設為零),您仍未取得平行計畫,可能是因為查詢規劃器無法為您的查詢產生平行計畫。請參閱 第 15.2 節第 15.4 節,以取得為何會這樣的原因資訊。

執行平行計畫時,您可以使用 EXPLAIN (ANALYZE, VERBOSE) 來顯示每個計畫節點的每個工作執行緒統計資料。這可能有助於確定工作是否平均分配到所有計畫節點,更一般地說,有助於了解計畫的效能特性。

提交修正

如果您在文件中看到任何不正確、與您對特定功能的經驗不符或需要進一步說明的地方,請使用 此表單 報告文件問題。