当优化器确定并行查询是针对特定查询最快的执行策略时,它将会创建一个查询计划,其中包含一个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
会按方便的任何顺序从处理程序读取元组,从而破坏可能存在的任何排序顺序。