系统中有若干硬性环境开关,若配置不当将使优化器在任何情况下都无法生成并行计划。要使系统具备生成并行计划的能力,以下关键参数必须满足要求:
max_parallel_workers_per_gather 的取值必须严格大于零。
此外,数据库系统不能运行于单用户维护模式(single-user mode)。在单用户模式下整个系统以单进程运行,无法调度后台工作进程。
即使全局环境支持并行,对于特定 SQL 查询,若命中以下任意条件,优化器同样不会为其生成并行执行计划:
查询涉及任何数据写入修改操作或行级加锁。若查询在顶层或 CTE 内部包含数据变更动作,该查询严禁生成并行计划。作为特例,以下创建新表并填充数据的命令,允许在其底层的 SELECT 查询部分使用并行计划:
CREATE TABLE ... AS
SELECT INTO
CREATE MATERIALIZED VIEW
REFRESH MATERIALIZED VIEW
查询在执行过程中可能被挂起或分批暂停。在任何可能发生分段、渐进式拉取数据的场景中,系统严禁生成并行计划。例如通过 DECLARE CURSOR 显式声明的游标查询绝不使用并行计划;PL/pgSQL 中形如 FOR x IN query LOOP .. END LOOP 的遍历循环同样绝不走并行,因为系统无法证明循环体代码在并行处于激活状态下的安全性。
查询中调用了被标记为 PARALLEL UNSAFE(并行不安全)的任何函数。绝大多数系统内置函数属于并行安全,但用户自定义函数在默认情况下均被系统保守地标记为并行不安全(详见 Section 15.4)。
查询本身正处于另一个已经处于并行执行的查询内部(不支持嵌套多级并行)。例如并行工作进程内部调用的函数若自身再次发起一条独立 SQL,该内部嵌套 SQL 绝不能再次开启并行,以防止单次业务操作引发进程数指数爆炸耗尽系统资源。
即使优化器为某条查询生成了并行计划,在运行时如果遭遇以下突发约束,该计划也无法以真正的多进程并发执行(此时由主 leader 进程独自串行执行完整计划):
因集群当前活跃的后台进程总数已达到 max_worker_processes 上限,无法申请到任何新 worker。
因整个集群当前正服务于并行查询的 worker 总数已达到 max_parallel_workers 上限。
客户端驱动通过扩展协议发送了带有非零抓取行数配额(fetch count)的 Execute 消息(分批游标拉取模式)。