当优化器确定并行查询是特定查询的最快执行策略时,它将创建一个包含 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
以方便的任何顺序从工作进程读取元组,破坏了任何可能存在的排序顺序。
如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步说明的内容,请使用 此表单 报告文档问题。