从零开始学PostgreSQL (十三):并行查询

2024-09-06 19:20:58 浏览数 (3)

概述

并行查询是PostgreSQL提供的一种功能,它允许查询在多个CPU核心或处理器上同时执行,从而显著提高查询性能,特别是在处理大型数据集时。并行查询的设计目标是在多核处理器的现代硬件上实现更好的资源利用率,减少查询响应时间。

并行查询的工作原理

在PostgreSQL中,当查询优化器决定并行查询是最佳执行策略时,它会构建一个查询计划,其中包含Gather或Gather Merge节点,这些节点管理并行任务的收集和整合工作。

代码语言:javascript复制
EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
                                     QUERY PLAN
-------------------------------------------------------------------------------------
 Gather  (cost=1000.00..217018.43 rows=1 width=97)
   Workers Planned: 2
   ->  Parallel Seq Scan on pgbench_accounts  (cost=0.00..216018.33 rows=1 width=97)
         Filter: (filler ~~ '%x%'::text)
(4 rows)
  1. 并行查询识别:优化器分析查询并确定是否并行执行能提高效率。如果适合并行化,查询计划将包括用于收集并行工作结果的Gather或Gather Merge节点,可以看到规划器选择的工作者(worker)数量。
  2. 并行工作分配:查询计划中的Gather或Gather Merge节点具有一个子节点,这是要并行执行的部分。如果此节点位于计划的顶层,整个查询将并行运行;否则,仅在该节点下的部分将并行执行。
  3. 工作者进程:查询执行到达Gather节点时,主进程将启动指定数量的后台工作者进程,这个数量由优化器确定,受max_parallel_workers_per_gather参数限制。工作者执行并行计划部分。
  4. 资源限制:总的后台工作者数受到max_worker_processes和max_parallel_workers参数的限制,这意味着实际运行的工作者数量可能少于计划中的数量,影响查询性能。
  5. 领导者角色:领导者(主进程)也参与并行计划的执行,但主要职责是收集和处理工作者产生的数据。如果并行部分产生大量数据,领导者可能主要忙于数据整合而非并行计算。
  6. 排序合并:Gather Merge节点用于当并行部分按排序顺序产生结果时,领导者执行保持排序的合并操作。Gather节点则不保证排序,从工作者接收数据而不保留原有排序。

并行查询的适用条件

并行查询在PostgreSQL中是一项可以显著提高查询性能的功能,但其使用受到多种因素的限制。以下是一些关键的配置和条件,它们决定了并行查询是否可以被应用:

必要配置

  1. max_parallel_workers_per_gather必须设置为大于零的值。这意味着至少有一个并行工作者可以被用于并行查询计划的执行。
  2. 系统不能处于单用户模式。在单用户模式下,整个数据库系统作为单一进程运行,因此无法启动背景工作者进程。

不适用情况

即使并行查询计划理论上可以生成,但如果出现以下情况之一,查询优化器将不会生成并行计划:

  1. 查询涉及数据写入或行级锁:如果查询包含数据修改操作(无论是顶级操作还是公共表表达式(CTE)内的操作),则不会为该查询生成并行计划。例外情况是创建新表并填充数据的命令,这些命令可以使用并行计划: CREATE TABLE ... AS SELECT INTO CREATE MATERIALIZED VIEW REFRESH MATERIALIZED VIEW
  2. 查询可能在执行过程中被挂起:如果系统认为查询的执行可能会被部分或增量的中断,那么不会生成并行计划。例如,使用DECLARE CURSOR创建的游标永远不会使用并行计划。同样地,形式如FOR x IN query LOOP ... END LOOP的PL/pgSQL循环也不会使用并行计划,因为并行查询系统无法确保循环代码在并行查询活跃时安全执行。
  3. 查询使用了标记为PARALLEL UNSAFE的函数:大多数系统定义的函数是PARALLEL SAFE的,但用户定义的函数默认被标记为PARALLEL UNSAFE。详情请参考第15.4节。
  4. 查询在另一个已经并行的查询内部运行:例如,如果一个并行查询调用的函数自身发出SQL查询,那么该查询将不会使用并行计划。这是一个当前实现的限制,而且可能不希望移除这一限制,以免单个查询使用过多的进程。

执行时的限制

即使为特定查询生成了并行查询计划,在执行时也可能因以下情况之一而无法并行执行:

  1. 背景工作者不足:如果由于max_worker_processes的限制,无法获取到足够的背景工作者。
  2. 并行工作者数量超出限制:如果由于max_parallel_workers的限制,无法获取到足够的并行工作者。
  3. 客户端发送带有非零获取计数的Execute消息:这通常发生在不依赖libpq的客户端中。如果这种情况频繁发生,可以考虑在可能发生串行执行的会话中将max_parallel_workers_per_gather设置为零,以避免生成在串行执行时可能次优的查询计划。

注意事项

  • 并行查询的效率受到系统资源的限制,特别是CPU核心数和内存大小。过多的并行工作线程可能会导致资源争抢,反而降低性能。
  • 并行查询在某些情况下可能不会带来性能提升,例如当查询涉及的数据量较小时,或者系统资源有限时。
  • 查询优化器可能会决定某些查询不适合并行处理,这取决于查询的具体情况和系统的配置。

总结

并行查询是PostgreSQL中一种强大的性能增强工具,尤其适用于需要处理大量数据的复杂查询。通过合理配置和使用并行查询,可以显著缩短查询响应时间,提高数据库的整体吞吐量。然而,正确地使用并行查询需要对系统的硬件资源、查询特性以及PostgreSQL的查询优化机制有深入的理解。在实践中,应当根据具体的硬件环境和查询需求,灵活调整并行查询的使用策略,以达到最佳的性能效果。

0 人点赞