PostgreSQL 中的
PARALLEL SAFE
是一个函数属性声明,用于明确告知查询规划器:该函数在并行执行上下文中是安全的,可以被下推到并行工作进程(worker)中执行。它不是“开启并行”的开关,而是“允许并行”的前提条件之一。
PARALLEL SAFE 的作用与意义
当 PostgreSQL 启动并行查询(如并行顺序扫描、并行聚合等)时,规划器会检查涉及的函数是否标记为
PARALLEL SAFE
。若函数未声明或声明为
PARALLEL RESTRICTED
/
PARALLEL UNSAFE
,则整个并行计划可能被降级为串行执行,或相关计算被迫保留在主进程(leader)中完成,削弱并行收益。
注意:
PARALLEL SAFE 不代表函数一定会被并行调用
,它只是移除了并行执行的障碍;是否真正并行,还取决于查询结构、成本估算、
设置及系统资源等。
三种并行兼容性级别对比
PostgreSQL 定义了三个函数并行安全性级别,必须显式指定(默认为
PARALLEL RESTRICTED
):
PARALLEL SAFE
:函数不访问共享状态(如序列、临时表、客户端连接信息)、不修改数据库、不依赖会话级变量(如
、
)、不调用非 SAFE 函数。可安全地在任意 worker 进程中多次执行。
PARALLEL RESTRICTED
:函数可在 leader 进程中执行,但不能下推至 worker(例如依赖
、
或写入临时表)。这是用户自定义函数的默认级别。
PARALLEL UNSAFE
:函数存在明显副作用或状态依赖(如修改全局变量、调用
、执行 DML),禁止在并行上下文中调用,否则可能导致错误或数据不一致。
如何正确声明 PARALLEL SAFE
在创建函数时,通过
子句显式指定:
CREATE OR REPLACE FUNCTION my_add(a int, b int)RETURNS int AS $$ SELECT a + b; $$LANGUAGE SQLPARALLEL SAFE;
关键注意事项:
所有被该函数直接或间接调用的其他函数,也必须是
PARALLEL SAFE
,否则声明无效,建表时会报错。
函数体中不可出现:
/
(序列)、
、
、
、对临时表的读写、PL/pgSQL 的
等。
纯计算类函数(如字符串处理、数学运算、JSON 解析)通常天然适合标记为
PARALLEL SAFE
;含 I/O、状态变更、事务/会话依赖的操作需谨慎评估。
验证与调试技巧
可通过系统视图确认函数的并行属性:
SELECT proname, proparallelFROM pg_procWHERE proname = 'my_add';
返回值含义:
=SAFE,
=RESTRICTED,
=UNSAFE。
启用并行查询后,使用
查看执行计划,观察函数调用是否出现在
节点之下(即由 worker 执行),是判断其是否真正并行化的直接依据。
max_parallel_workers_per_gathercurrent_usersession_userpg_backend_pid()clock_timestamp()dblinkPARALLELNEXTVALCURRVALtxid_current()pg_snapshot_xmin()set_config()GET DIAGNOSTICSsruEXPLAIN (ANALYZE, VERBOSE)Gather