Postgresql 中文操作指南
15.4. Parallel Safety #
计划器将查询中涉及的操作分类为 parallel safe、parallel restricted 或 parallel unsafe。并行安全操作不会与并行查询的使用产生冲突。并行受限操作不能在并行工作器中执行,但可以在并行查询使用期间在领导者中执行。因此,并行受限操作永远不能出现在 Gather 或 Gather Merge 节点下面,但可以在包含此类节点的计划中的其他位置出现。并行不安全操作不能在并行查询使用期间执行,甚至不能在领导者中执行。当查询包含任何与并行不安全相关的内容时,将为该查询完全禁用并行查询。
以下操作始终是并行受限的:
15.4.1. Parallel Labeling for Functions and Aggregates #
规划器无法自动确定用户自定义函数或聚合是并行安全的、并行受限的还是并行不安全的,因为这需要预测函数可能执行的每一项操作。总的来说,这等同于停机问题,因此是不可能的。即使对于可以想象可以执行的简单函数,我们也不会尝试,因为这将非常昂贵且容易出错。相反,除非另有标记,否则所有用户自定义函数都假定为并行不安全。当使用 CREATE FUNCTION 或 ALTER FUNCTION 时,可以通过适当地指定 PARALLEL SAFE 、 PARALLEL RESTRICTED 或 PARALLEL UNSAFE 来设置标记。当使用 CREATE AGGREGATE 时,可以将 PARALLEL 选项指定为 SAFE 、 RESTRICTED 或 UNSAFE 作为对应的值。
如果函数和聚合写入数据库、访问序列、更改事务状态,即使是暂时更改(例如,建立 EXCEPTION 块以捕获错误的 PL/pgSQL 函数),或者对设置进行持久更改,则必须将它们标记为 PARALLEL UNSAFE。类似地,如果函数访问临时表、客户端连接状态、游标、预处理语句或系统无法跨工作器同步的其他后端本地状态,则必须将它们标记为 PARALLEL RESTRICTED。例如,出于此最后原因,setseed 和 random 是并行受限的。
一般而言,如果一个函数被标注为受限或不安全时被标记为安全,或者如果一个函数被标注为受限,而事实上它是 不安全的,那么当在并行查询中使用它时,它可能会引发错误或生成错误答案。如果标注错误,用 C 语言编写的函数理论上可能表现出完全未定义的行为,因为系统无法保护自身免遭任意的 C 代码,但在大多数情况下,结果不会比任何其他函数差。如有疑问,最好将函数标记为 UNSAFE。
如果在并行工作进程中执行的函数获取了领导者不持有的锁,例如通过查询未在查询中引用的表,这些锁将在工作进程退出时释放,而不会在事务结束时释放。如果您编写了执行此操作的函数,并且这种行为差异对您很重要,请将此类函数标记为 PARALLEL RESTRICTED 以确保它们仅在领导者中执行。
请注意,查询计划器不会考虑延迟查询中涉及的并行受限函数或聚合的评估,以获取更好的计划。因此,例如,如果应用于特定表的 WHERE 语句受并行限制,则查询计划器将不会考虑在计划的并行部分中扫描该表。在某些情况下,可以在查询的并行部分中包含该表的扫描并且延迟评估 WHERE 语句,以便它发生在 Gather 节点之上,这是可能的(甚至可能是有效的)。但是,计划器不会执行此操作。