文章目录

PostgreSQL并行查询Worker进程数与Gather节点调度

发布于 2026-06-18 09:38:39 · 浏览 10 次 · 评论 0 条

PostgreSQL并行查询Worker进程数与Gather节点调度

PostgreSQL的并行查询功能允许单个查询操作分解为多个子任务,由多个工作进程(Worker)同时执行,从而大幅缩短大型查询的响应时间。理解并控制这一过程的关键,在于掌握Worker进程的数量配置以及协调它们的核心组件——Gather节点的调度逻辑。本指南将带你一步步配置和理解这些机制。


理解并行查询与Gather节点

并行查询的核心是将扫描、聚合、连接等操作分配给多个工作进程并行完成。协调这些工作进程的核心是计划树中的Gather节点。你可以将它想象成一个“项目经理”或“工头”。

  • Gather节点:位于计划树中需要并行执行的部分之上。它的主要职责是启动一个或多个工作进程,并将任务(如扫描某个表的不同数据块)分配给它们。然后,它负责收集所有工作进程返回的结果,进行汇总(例如排序或去重),最终将完整结果返回给主进程。
  • Worker进程:是实际执行任务的“工人”。它们由Gather节点启动,在数据库启动时预先分配好的“进程池”中获取。

核心参数:并行能力的强弱主要受三个服务器参数控制,它们像三个阀门,共同决定了能有多少Worker可供使用。


核心参数设置与检查

在配置并行度前,检查当前数据库的默认设置。

# 使用psql或任何SQL客户端连接到数据库后执行
SHOW max_worker_processes;
SHOW max_parallel_workers;
SHOW max_parallel_workers_per_gather;

这三个参数从宽到窄,形成了三层约束:

  1. max_worker_processes:系统允许启动的所有类型后台工作进程的总上限(包括并行查询Worker、逻辑复制Worker等)。这是一个全局硬上限。
  2. max_parallel_workers:专门用于并行查询的Worker进程池的大小。它必须小于或等于max_worker_processes
  3. max_parallel_workers_per_gather:单个查询中的一个Gather节点最多能使用多少个Worker进程。这是最直接控制单条查询并行度的参数。

配置示例:假设你的服务器有8核CPU,希望为并行查询留足资源。

-- 在postgresql.conf文件中修改,或使用ALTER SYSTEM命令(需重启或重载配置)
ALTER SYSTEM SET max_worker_processes = 16; -- 总进程数留有余地
ALTER SYSTEM SET max_parallel_workers = 12; -- 给并行查询分配一个较大的池
ALTER SYSTEM SET max_parallel_workers_per_gather = 4; -- 每个Gather节点最多用4个Worker

修改后,执行 SELECT pg_reload_conf(); 或重启数据库使配置生效。


Gather节点如何调度Worker

当你执行一个可能并行的查询时,查询规划器(Planner)会生成计划。如果它认为并行执行更高效,就会在计划树中插入Gather节点。调度过程如下:

graph TD A[用户执行查询] --> B{查询规划器生成计划}; B --> C[计划包含Gather节点]; C --> D[Executor执行到Gather节点]; D --> E["Gather节点\n向‘进程池’申请Worker"]; F{"可用Worker数 >=\n`max_parallel_workers_per_gather`?"}; E --> F; F -- 是 --> G["启动 `max_parallel_workers_per_gather` 个Worker"]; G --> H[将任务(如数据块扫描)拆分并分配]; H --> I[Worker并行执行子任务]; I --> J[Gather节点收集结果并汇总]; J --> K[返回最终结果]; F -- 否 --> L["启动所有可用Worker\n(可能少于 `per_gather` 设置)"]; L --> H;

关键点

  • Gather节点启动的Worker数量,取 max_parallel_workers_per_gather当时并行Worker进程池中可用进程数较小值
  • 如果池中可用进程不足,查询会降级为用更少的Worker执行,甚至退化为单进程执行,但不会报错。
  • 一个复杂查询可能包含多个Gather节点(例如在复杂JOIN的多个子查询上),它们会竞争同一个max_parallel_workers进程池。

实战:配置与验证并行查询

遵循以下步骤,为你的数据库优化并行查询能力。

1. 评估硬件与工作负载
评估你的服务器CPU核心数。通常,max_parallel_workers_per_gather 设置为CPU核心数的1/4到1/2是一个不错的起点。设置过高可能导致CPU争抢和I/O瓶颈。

2. 修改核心参数
连接到数据库服务器,编辑 postgresql.conf 文件。
添加或修改以下行(根据你的评估调整数值):

max_worker_processes = 16
max_parallel_workers = 12
max_parallel_workers_per_gather = 4

重载配置:SELECT pg_reload_conf(); 或重启数据库。

3. 创建测试环境并插入数据
为了观察并行效果,创建一个足够大的表。

CREATE TABLE large_table (id serial, data text, created_at timestamp);
INSERT INTO large_table (data, created_at)
SELECT md5(random()::text), now() - (random() * 1000 || ' days')::interval
FROM generate_series(1, 10000000); -- 生成一千万条测试数据
ANALYZE large_table; -- 收集统计信息,帮助规划器做出正确决策

4. 执行并分析查询
打开并行查询提示,然后执行一个大型扫描查询。

-- 首先,强制显示详细计划(可选,但能清晰看到Gather节点)
EXPLAIN (ANALYZE, BUFFERS) SELECT count(*), min(created_at), max(created_at) FROM large_table;

EXPLAIN ANALYZE 的输出中,查找带有 -> Gather 的行。你会看到类似 Workers Planned: 4, Workers Launched: 4 的信息。这表明规划器计划使用4个Worker,且成功启动了4个。如果看到 Workers Launched: 0,则表示并行被禁用或无法启动Worker。

5. 动态调整与排查

  • 临时禁用并行:在会话级设置 SET max_parallel_workers_per_gather = 0;,再次执行查询,对比执行时间。
  • 检查限制:如果计划中没有出现Gather节点,可能因为查询本身太简单(成本低于 min_parallel_table_scan_sizemin_parallel_index_scan_size 阈值),或表缺少统计信息。
  • 监控进程:在操作系统层面,使用 ps aux | grep postgres 可以观察到大量名为 parallel worker 的进程。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文