15.4. 并行安全

计划者将查询中涉及的操作分类为* parallel safe parallel limited parallel unsafe *。并行安全操作是一种与并行查询的使用不冲突的操作。并行受限操作是不能在并行工作程序中执行的操作,但是可以在使用并行查询时在领导者中执行。因此,并行受限操作永远不会在GatherGather Merge节点下发生,而可能在包含此类节点的计划中的其他地方发生。并行不安全操作是在使用并行查询时无法执行的操作,即使在领导者中也是如此。当查询包含并行不安全的任何内容时,该查询将完全禁用并行查询。

以下操作始终受到并行限制。

  • 扫描公用表表达式(CTE)。

  • 扫描临时表。

  • 扫描外部表,除非外部数据包装器具有IsForeignScanParallelSafe API,否则该指示。

  • 访问InitPlan或相关的SubPlan

15 .4.1. 功能和集合的并行标记

计划者无法自动确定用户定义的函数或集合是并行安全的,并行受限的还是并行不安全的,因为这将需要预测该函数可能执行的每个操作。通常,这等效于停止问题,因此是不可能的。即使对于可能可以实现的简单功能,我们也不会尝试,因为这样做会很昂贵并且容易出错。取而代之的是,除非另有说明,否则所有用户定义的函数均假定为并行不安全的。使用CREATE FUNCTIONALTER FUNCTION时,可以通过适当地指定PARALLEL SAFEPARALLEL RESTRICTEDPARALLEL UNSAFE来设置标记。使用CREATE AGGREGATE时,可以使用SAFERESTRICTEDUNSAFE作为对应值来指定PARALLEL选项。

如果函数和集合写入数据库,访问序列,甚至临时更改事务状态(例如,构建EXCEPTION块以捕获错误的 PL/pgSQL 函数)或对设置进行永久更改,则它们必须标记为PARALLEL UNSAFE。同样,如果函数访问临时表,Client 端连接状态,游标,准备好的语句或系统无法跨工作程序同步的其他后端本地状态,则必须将它们标记为PARALLEL RESTRICTED。例如,出于最后一个原因,setseedrandom被并行限制。

通常,如果某个函数在受限或不安全时被标记为安全,或者在实际上不安全时被标记为受限,则在并行查询中使用该函数时可能会引发错误或产生错误的答案。如果标注错误,C 语言函数在理论上可能会表现出完全未定义的行为,因为系统无法保护自己免受任意 C 代码的侵害,但是在大多数情况下,其结果不会比其他函数差。如有疑问,最好将函数标记为UNSAFE

如果在并行工作程序中执行的函数获取了领导者未持有的锁,例如通过查询查询中未引用的表,则这些锁将在工作程序 Export 而不是事务结束时释放。如果您编写了执行此操作的函数,并且这种行为差异对您很重要,则将此类函数标记为PARALLEL RESTRICTED,以确保它们仅在前导中执行。

请注意,查询计划者不会考虑为了获得上级计划而推迟对查询中涉及的并行限制函数或集合的求值。因此,例如,如果并行限制了应用于特定表的WHERE子句,则查询计划者将不考虑在计划的并行部分中对该表进行扫描。在某些情况下,有可能(甚至可能有效)将对该表的扫描包括在查询的并行部分中,并推迟对WHERE子句的求值,使其发生在Gather节点上方。但是,计划者不会这样做。