當優化器判斷對于某一個特定的查詢,并行查詢是最快的執行策略時,優化器將創建一個查詢計劃。
該計劃包括一個 Gather或者Gather Merge節點。下面是一個簡單的例子:
EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
QUERY PLAN
-------------------------------------------------------------------?------------------
Gather (cost=1000.00..217018.43 rows=1 width=97)
Workers Planned: 2
-> Parallel Seq Scan on pgbench_accounts (cost=0.00..216018.33 rows=1 width=97)
Filter: (filler ~~ '%x%'::text)
(4 rows)
在所有的情形下,Gather
或Gather Merge節點都只有一個子計劃,它是將被并行執行的計劃的一部分。如果Gather
或Gather Merge節點位于計劃樹的最頂層,那么整個查詢將并行執行。如果它位于計劃樹的其他位置,那么只有查詢中在它之下的那一部分會并行執行。在上面的例子中,查詢只訪問了一個表,因此除Gather
節點本身之外只有一個計劃節點。因為該計劃節點是Gather
節點的孩子節點,所以它會并行執行。
使用 EXPLAIN 命令, 你能看到規劃器選擇的工作者數量。當查詢執行期間到達Gather
節點時,實現用戶會話的進程將會請求和規劃器選中的工作者數量一樣多的后臺工作者進程 。規劃器將考慮使用的后臺工作者的數量被限制為最多 max_parallel_workers_per_gather 個。任何時候能夠存在的后臺工作者進程的總數由 max_worker_processes 和 max_parallel_workers 限制。因此,一個并行查詢可能會使用比規劃中少的工作者來運行,甚至有可能根本不使用工作者。最優的計劃可能取決于可用的工作者的數量,因此這可能會導致不好的查詢性能。如果這種情況經常發生,那么就應當考慮一下提高max_worker_processes
和max_parallel_workers
的值,這樣更多的工作者可以同時運行;或者降低max_parallel_workers_per_gather
,這樣規劃器會要求少一些的工作者。
為一個給定并行查詢成功啟動的后臺工作者進程都將會執行計劃的并行部分。這些工作者的領導者也將執行該計劃,不過它還有一個額外的任務:它還必須讀取所有由工作者產生的元組。當整個計劃的并行部分只產生了少量元組時,領導者通常將表現為一個額外的加速查詢執行的工作者。反過來,當計劃的并行部分產生大量的元組時,領導者將幾乎全用來讀取由工作者產生的元組并且執行Gather
或Gather Merge
節點上層計劃節點所要求的任何進一步處理。在這些情況下,領導者所作的執行并行部分的工作將會很少。
當計劃的并行部分的頂層節點是Gather Merge
而不是Gather
時,它表示每個執行計劃并行部分的進程會產生有序的元組,并且領導者執行一種保持順序的合并。相反,Gather
會以任何方便的順序從工作者讀取元組,這會破壞可能已經存在的排序順序。