parallel_setup_cost 是 postgresql 估算启动并行计划额外开销的参数,影响优化器是否选择并行路径;其值过高会导致即使数据量大、cpu 空闲也不启用并行,需结合 explain 和实际负载合理调优。

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










