15.2. 何时可以使用并行查询?#
有几个设置可能导致查询计划程序在任何情况下都不生成并行查询计划。为了生成任何并行查询计划,必须按指示配置以下设置。
max_parallel_workers_per_gather 必须设置为大于零的值。这是更通用原则的一个特例,即不应使用超过通过
max_parallel_workers_per_gather
配置的 worker 数量。
此外,系统不得在单用户模式下运行。由于在这种情况下整个数据库系统都作为一个进程运行,因此不会有后台 worker 可用。
即使通常可以生成并行查询计划,如果满足以下任何条件,规划器也不会为给定查询生成并行查询计划
查询写入任何数据或锁定任何数据库行。如果查询在顶级或 CTE 内包含数据修改操作,则不会生成该查询的并行计划。但以下命令除外,这些命令创建新表并填充新表,可以使用并行计划来处理查询的底层
SELECT
部分CREATE TABLE ... AS
SELECT INTO
CREATE MATERIALIZED VIEW
REFRESH MATERIALIZED VIEW
查询在执行期间可能会被挂起。在系统认为可能会发生部分或增量执行的任何情况下,都不会生成并行计划。例如,使用 DECLARE CURSOR 创建的游标永远不会使用并行计划。类似地,形式为
FOR x IN query LOOP .. END LOOP
的 PL/pgSQL 循环永远不会使用并行计划,因为并行查询系统无法验证循环中的代码在并行查询处于活动状态时是否安全执行。查询使用标记为
PARALLEL UNSAFE
的任何函数。大多数系统定义函数都是PARALLEL SAFE
,但默认情况下用户定义函数标记为PARALLEL UNSAFE
。请参阅 第 15.4 节 的讨论。查询在已并行的另一个查询内运行。例如,如果并行查询调用的函数本身发出 SQL 查询,则该查询永远不会使用并行计划。这是当前实现的一个限制,但删除此限制可能不可取,因为它可能导致单个查询使用大量进程。
即使为特定查询生成了并行查询计划,在执行时也有几种情况无法并行执行该计划。如果发生这种情况,领导者将完全自行执行Gather
节点下方的计划部分,几乎就像Gather
节点不存在一样。如果满足以下任何条件,就会发生这种情况
由于后台工作进程总数不能超过 max_worker_processes 的限制,因此无法获取后台工作进程。
由于为并行查询启动的后台工作进程总数不能超过 max_parallel_workers 的限制,因此无法获取后台工作进程。
客户端发送具有非零获取计数的 Execute 消息。请参阅 扩展查询协议 的讨论。由于 libpq 目前不提供发送此类消息的方法,因此仅当使用不依赖于 libpq 的客户端时才会发生这种情况。如果这种情况经常发生,则最好在可能发生这种情况的会话中将 max_parallel_workers_per_gather 设置为零,以避免生成在串行运行时可能不理想的查询计划。