parallel_workers = 0 是硬性禁止并行,直接跳过并行计划生成;max_parallel_workers_per_gather 才是单查询并行度上限,parallel_workers 仅为意向值,最终取三者最小值。

parallel_workers 设为 0 是真禁用并行,不是“忽略”
很多人以为 parallel_workers = 0 只是“不主动启用”,其实它是硬性禁止:PostgreSQL 遇到这个设置会直接跳过并行计划生成,哪怕查询本身很重、max_parallel_workers 也足够。它比 force_parallel_mode = off 更底层,作用在表扫描阶段就截断了。
实操建议:
- 调试时想彻底排除并行干扰,设
parallel_workers = 0比调全局参数更精准 - 生产中慎用,尤其对大分区表——某些场景下强制串行反而让单核跑满、拖慢整体响应
- 注意它只影响该表的顺序扫描(Seq Scan)和位图堆扫描(Bitmap Heap Scan),索引扫描不受控
max_parallel_workers 是全局闸门,但不保证每个查询都分到额度
max_parallel_workers 是整个实例能同时运行的 worker 进程上限,不是“每查询可用数”。当多个查询并发执行,它们共享这个池子;一个查询申请 4 个 worker,另一个可能只能分到 1 个,甚至 0 个——取决于当时剩余配额和查询代价估算。
常见错误现象:
- 单个大查询没走并行,查
EXPLAIN显示Workers Planned: 0,但max_parallel_workers明明设了 8 → 实际是其他后台任务(如 VACUUM、后台 worker)占满了额度 - 提高
max_parallel_workers后性能没提升,反而出现内存 OOM → 并行 worker 共享work_mem,总数翻倍意味着总内存消耗可能翻几倍
表级 parallel_workers 超过 max_parallel_workers_per_gather 会被截断
PostgreSQL 真正限制单个查询并行度的是 max_parallel_workers_per_gather(默认 2),不是 max_parallel_workers。即使你给某张表设了 parallel_workers = 8,只要 max_parallel_workers_per_gather = 2,该查询最多只用 2 个 worker。
关键点:
-
parallel_workers是“意向值”,最终生效数取min(表设置, max_parallel_workers_per_gather, 剩余全局额度) - 修改
max_parallel_workers_per_gather需要重启(9.6–13)或 reload(14+),但改表级parallel_workers可在线执行ALTER TABLE ... SET (parallel_workers = N) - 对小表设高值(如 4)没意义——优化器会因代价低自动降为 0,不会真启 worker
并行度实际生效要看执行计划里的 Workers Launched
EXPLAIN (ANALYZE) 输出里 Workers Launched: 2 才代表真起了并行,光看 Workers Planned: 2 不够。后者只是优化器预估,可能因 runtime 资源不足、锁冲突、函数不可并行(比如含 random() 或未标记 PARALLEL SAFE 的 UDF)而 fallback。
容易被忽略的地方:
- 某些内置函数(如
pg_sleep()、txid_current())默认不是PARALLEL SAFE,一用就让整个 plan 退化为串行 - 分区表下,如果父表没设
parallel_workers,而子表设了,PostgreSQL 9.6–12 不继承,13+ 才支持继承(需显式SET到父表) - 并行 worker 不共享 session 设置,比如你在会话里
SET work_mem = '512MB',worker 仍用配置文件里的默认值
调参这事,盯着 Workers Launched 比盯着配置项数字管用得多。数值飘忽不定,往往不是配少了,而是某处隐式阻断了并行路径。










