有几种设置会导致查询规划器在任何情况下都不生成并行查询计划。为了让并行查询计划能够被生成,必须配置好下列设置。
max_parallel_workers_per_gather必须被设置为大于零的值。这是一种特殊情况,更加普遍的原则是所用的工作者数量不能超过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
。参见第 15.4 节中的讨论。
该查询运行在另一个已经存在的并行查询内部。例如,如果一个被并行查询调用的函数自己发出一个 SQL 查询,那么该查询将不会使用并行计划。这是当前实现的一个限制,但是或许不值得移除这个限制,因为它会导致单个查询使用大量的进程。
事务隔离级别是可串行化。这是当前实现的一个限制。
即使对于一个特定的查询已经产生了并行查询计划,在一些情况下执行时也不会并行执行该计划。如果发生这种情况,那么领导者将会自己执行该计划在Gather
节点之下的部分,就好像Gather
节点不存在一样。上述情况将在满足下面的任一条件时发生:
因为后台工作者进程的总数不能超过max_worker_processes,导致不能得到后台工作者进程。
由于为并行查询而启动的后台工作者总数不能超过 max_parallel_workers,因此无法获得后台工作者。
客户端发送了一个执行消息,并且消息中要求取元组的数量不为零。执行消息可见扩展查询协议中的讨论。因为libpq当前没有提供方法来发送这种消息,所以这种情况只可能发生在不依赖 libpq 的客户端中。如果这种情况经常发生,那在它可能发生的会话中将max_parallel_workers_per_gather设置为0是一个很好的主意,这样可以避免产生连续运行时次优的查询计划。
准备好的语句是使用CREATE TABLE .. AS EXECUTE ..
语句执行的。
此构造将本来只是只读操作的内容转换为读写操作,使其不适合并行查询。
事务隔离级别是可串行化。这种情况通常不会出现,因为当事务隔离级别是可串行化时不会产生并行查询计划。不过,如果在产生计划之后并且在执行计划之前把事务隔离级别改成可串行化,这种情况就有可能发生。