15.1. 并行查询的工作方式

当优化器确定并行查询是特定查询的最快执行策略时,它将创建一个包含* 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)

在所有情况下,GatherGather Merge节点都将只有一个子计划,这是计划中将并行执行的部分。如果GatherGather Merge节点位于计划树的最顶部,则整个查询将并行执行。如果它在计划树中的其他位置,则仅计划下方的部分将并行运行。在上面的示例中,查询仅访问一个表,因此,除了Gather节点本身之外,仅存在一个计划节点。由于该计划节点是Gather节点的子节点,因此它将并行运行。

Using EXPLAIN,您可以看到计划者选择的 Worker 数量。当在查询执行过程中到达Gather节点时,实现用户会话的过程将请求后台工作程序的数量,该数量等于计划者选择的工作人员的数量。计划人员将考虑使用的后台工作者的数量最多为max_parallel_workers_per_gather。一次可以存在的后台工作者总数受max_worker_processesmax_parallel_workers限制。因此,并行查询有可能以少于计划的工作人员运行,甚至根本没有工作。最佳计划可能取决于可用工作程序的数量,因此这可能会导致查询性能下降。如果这种情况经常发生,请考虑增加max_worker_processesmax_parallel_workers以便可以同时运行更多的 Worker,或者减少max_parallel_workers_per_gather以便计划者减少 Worker 的数量。

对于给定的并行查询成功启动的每个后台工作进程将执行计划的并行部分。领导者还将执行计划的那部分,但是它还有另外的责任:它还必须读取 Worker 产生的所有 Tuples。当计划的并行部分仅生成少量 Tuples 时,领导者的行为通常会非常类似于额外的工作程序,从而加快了查询的执行速度。相反,当计划的并行部分生成大量 Tuples 时,领导者可能几乎完全被读取 Worker 所生成的 Tuples 并执行高于Gather节点级别的计划节点所需的任何其他处理步骤所占据或Gather Merge节点。在这种情况下,领导者将很少执行计划的并行部分的工作。

当计划的并行部分顶部的节点是Gather Merge而不是Gather时,表明执行计划的并行部分的每个进程都按排序 Sequences 生成 Tuples,并且领导者正在执行 Sequences 保留合并。相反,Gather以方便的任何 Sequences 从工作者读取 Tuples,从而破坏了可能存在的任何排序 Sequences。