15.2. 什么时候可以使用并行查询?

有几种设置可能导致查询计划程序在任何情况下都不生成并行查询计划。为了生成任何并行查询计划,必须按照指示配置以下设置。

  • max_parallel_workers_per_gather必须设置为大于零的值。这是更为普遍的原则的特例,即不应使用的 Worker 数量应大于通过max_parallel_workers_per_gather配置的数量。

  • dynamic_shared_memory_type必须设置为none以外的其他值。并行查询需要动态共享内存,以便在协作进程之间传递数据。

此外,系统不得在单用户模式下运行。由于在这种情况下整个数据库系统都在单个进程中运行,因此没有后台工作人员可用。

即使通常有可能生成并行查询计划,但如果满足以下任一条件,计划程序也不会为给定查询生成它们:

  • 该查询将写入任何数据或锁定任何数据库行。如果查询在顶层或 CTE 内包含数据修改操作,则不会为该查询生成并行计划。这是当前实施的限制,可以在将来的版本中取消。

  • 该查询可能在执行期间被挂起。在系统认为可能发生部分或增量执行的任何情况下,都不会生成并行计划。例如,使用DECLARE CURSOR创建的游标将永远不会使用并行计划。同样,格式为FOR x IN query LOOP .. END LOOP的 PL/pgSQL 循环将永远不会使用并行计划,因为在并行查询处于活动状态时,并行查询系统无法验证循环中的代码是否可以安全执行。

  • 该查询使用任何标记为PARALLEL UNSAFE的函数。大多数系统定义的函数为PARALLEL SAFE,但默认情况下用户定义的函数标记为PARALLEL UNSAFE。请参阅Section 15.4的讨论。

  • 该查询正在另一个已经并行的查询中运行。例如,如果并行查询调用的函数本身发出 SQL 查询,则该查询将永远不会使用并行计划。这是当前实现的限制,但是可能不希望删除此限制,因为它可能导致使用大量进程进行单个查询。

  • 事务隔离级别是可序列化的。这是当前实现的限制。

即使为特定查询生成了并行查询计划,在几种情况下,也无法在执行时并行执行该计划。如果发生这种情况,领导者将完全独自执行Gather节点下的计划部分,几乎就像Gather节点不存在一样。如果满足以下任一条件,就会发生这种情况:

  • 由于后台工作者的总数不能超过max_worker_processes的限制,因此无法获得后台工作者。

  • 由于存在以下限制,因此无法获得后台工作人员:为并行查询目的启动的后台工作人员总数不能超过max_parallel_workers

  • Client 端发送的执行消息的读取计数非零。请参阅扩展查询协议的讨论。由于libpq当前不提供发送此类消息的方法,因此只有在使用不依赖 libpq 的 Client 端时,才会发生这种情况。如果这是经常发生的情况,则在可能的会话中将max_parallel_workers_per_gather设置为零可能是个好主意,从而避免生成在串行运行时可能次优的查询计划。

  • 使用CREATE TABLE .. AS EXECUTE ..语句执行准备好的语句。此构造将原本可能是只读的操作转换为读写操作,从而使其不符合并行查询的条件。

  • 事务隔离级别是可序列化的。通常不会出现这种情况,因为在事务隔离级别可序列化时不会生成并行查询计划。但是,如果在计划生成之后和执行之前将事务隔离级别更改为可序列化,则会发生这种情况。