postgresql 16 的并行 group by 仅对支持 partial/final 模式的聚合函数(如无 order by 的 string_agg、array_agg 等)且满足数据量、成本阈值等条件时生效;需调参并验证 explain 中的 gather 与 partial aggregate 节点。

PostgreSQL 16 的并行 GROUP BY 不是“设了参数就自动变快”,它只对特定聚合函数 + 特定写法生效,且默认配置下大概率不触发。
哪些 GROUP BY 场景真能并行?
只有满足「可拆分(partial)+ 可合并(final)」的聚合函数才可能走并行路径。关键看是否支持 Partial Mode:
-
string_agg(col, ',')—— 无ORDER BY才行;带ORDER BY直接退化为串行 -
array_agg(col)、json_agg(col)、jsonb_agg(col)—— 同样禁止ORDER BY -
sum()、max()、min()、count()—— 但count(distinct x)或avg(x)(16 之前)不行
常见错误现象:写了 GROUP BY id, string_agg(name, ',' ORDER BY name),EXPLAIN 却看不到 Gather 节点——不是配置问题,是语法本身不支持并行。
为什么 EXPLAIN 看不到 Gather 节点?
即使开了并行参数,优化器也可能跳过并行计划。主要原因有:
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
- 表太小:
min_parallel_table_scan_size默认是 8MB,扫描数据量低于该值,直接不考虑并行 - cost 压制:
parallel_setup_cost(默认 10)和parallel_tuple_cost(默认 0.1)过高,让并行预估成本 > 串行 - 含 volatile 函数(如
now()、random())、FOR UPDATE、或某些窗口函数,会禁用并行 - 底层聚合不支持 partial 阶段,比如
count(distinct x)无法分片计算再合并
验证是否生效最简单的方法:运行 EXPLAIN (ANALYZE, VERBOSE),看到 Gather 或 Gather Merge 节点,且子节点含 Partial Aggregate,才算真正并行。
怎么调参让并行 GROUP BY 跑起来?
默认配置对中小表几乎无效,必须手动干预几个关键参数(session 级即可,无需重启):
- 设 worker 数:
SET max_parallel_workers_per_gather = 4;(建议 ≤ CPU 核心数,别超max_worker_processes) - 降低门槛:
SET min_parallel_table_scan_size = 1MB;(测试可用,生产环境建议按实际表大小微调) - 压低开销:
SET parallel_setup_cost = 2;和SET parallel_tuple_cost = 0.01; - 注意
work_mem:总内存消耗 ≈(1 + max_parallel_workers_per_gather) × work_mem,设太小会导致磁盘排序,反而更慢
这些参数只影响当前 query,不会全局生效;但调得太激进(比如设 16 个 worker),在高并发场景下容易挤占其他查询资源。
最容易被忽略的点是:并行 GROUP BY 的收益高度依赖数据分布和聚合粒度。如果 GROUP BY 键的基数极低(比如只有 3–5 个分组),并行带来的调度和合并开销可能超过收益——这时候串行反而更快。










