parallel_setup_cost 是 PostgreSQL 估算启动并行计划额外开销的参数,影响优化器是否选择并行路径;其值过高会导致即使数据量大、CPU 空闲也不启用并行,需结合 EXPLAIN 和实际负载合理调优。
parallel_setup_cost 是什么,为什么它会影响查询是否走并行
它不是“并行越快越好”的开关,而是 PostgreSQL 估算「启动并行计划」额外开销的参数。优化器会把并行路径的总代价算成:
。只要这个总代价比串行计划低,才会选并行。所以它本质是**一道门槛**——跨不过去,哪怕数据量很大、CPU 很闲,也不会起 worker。
怎么调:从默认值开始观察,而不是瞎猜
PostgreSQL 默认
(单位是 seq_page_cost,即一次顺序读页的代价)。实际中这个值往往偏高,尤其在 SSD 或本地 NVMe 上,启动一个 worker 的真实开销远低于 1000 单位。
先查当前值:
用
看关键慢查询,确认它本该并行但没走——注意看执行计划里有没有
节点
临时调低测试:
,再跑
,观察是否出现并行分支
别一上来就设成 0:那会导致极小查询也拉 worker,反而因调度/同步开销变慢
容易踩的坑:和 parallel_tuple_cost、max_parallel_workers_per_gather 搞混
只管“启动”代价,不涉及后续数据分发或 tuple 处理。常见误操作:
调低了
却没动
(默认为 2),结果只起了 2 个 worker,但表有 1TB、8 核 CPU,明显没榨干资源
以为降低
(默认 0.1)能“鼓励”并行——其实它影响的是每个 tuple 分发到 worker 的代价估算,对是否启用并行影响极小,优先级远低于
在连接池层(如 pgbouncer)里 SET 参数无效:必须在业务连接内显式设置,或写进
/
后 reload
生产环境调优的关键信号:看 EXPLAIN 输出里的 actual time 和 Workers Launched
真正有效的调优不是看参数数字变小了,而是看执行计划是否发生了质变:
原来没有
,现在有了,且
→ 成功触发并行
虽然有
,但
中 worker 部分耗时远高于 leader,说明数据倾斜或 shared_buffers 不足 → 这时候调
没用,得查 JOIN 条件或索引
并发查询多时,
设太低会导致大量短查询争抢 worker,拖慢整体吞吐 → 建议结合
和负载特征做分级,比如 OLAP 查询专用连接池单独设低值
最常被忽略的一点:
对 hash join、bitmap scan 等特定节点类型敏感,但对 index scan 基本无效——如果你的慢查询主因是没走索引,调这个参数毫无意义。
sequential_plan_cost + parallel_setup_cost + (parallel_child_cost × 并行 worker 数)parallel_setup_cost = 1000SHOW parallel_setup_cost;EXPLAIN (ANALYZE, BUFFERS)GatherSET parallel_setup_cost = 100;EXPLAINparallel_setup_costparallel_setup_costmax_parallel_workers_per_gatherparallel_tuple_costparallel_setup_costpostgresql.confALTER SYSTEMGatherWorkers Launched: 3Gatheractual timeparallel_setup_costparallel_setup_costmax_worker_processesparallel_setup_cost