Postgresql 并行查询原理与实践

目录

环境

文档用途

详细信息

环境

系统平台:Linux x86-64 Red Hat Enterprise Linux 7

版本:10.3

文档用途

介绍Postgresql 并行查询原理与实践

详细信息

一、PG并行查询概要

PostgreSQL利用多 CPU 让查询更快的查询计划,这种特性被称为并行查询。

很多查询使用并行查询时比之前快了超过两倍,有些查询是以前的四倍甚至更多的倍数。那些访问大量数据但只返回其中少数行给用户的查询最能从并行查询中获益。

 

二、PG并行查询如何工作

优化器判断某一个特定的查询,并行查询是最快的执行策略时,将创建一个查询计划。

该计划包括一个Gather或Gather Merge节点。

 

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)

 

本例查询只访一张表,除Gather 节点本身之外只有一个计划节点。该计划节点是 Gather 节点的孩子节点,所以它会并行执行。 在所有情况下,Gather或 Gather Merge节点将只有一个子计划,这是将并行执行的计划部分;如果 Gather 或Gather Merge节点位于计划树的最顶层,那么整个查询将并行执行;如果它位于计划树的其他位置,那么只有在它下面的计划部分会并行执行。

 image.png

 

如上图所示为给定的并行查询成功启动的每个后台工作进程都将执行该计划的并行部分。领导者(Gather),也将执行计划的一部分,但它还有一个额外的责任:它还必须读取工人(workers)生成的所有元组。

当计划的并行部分仅生成少量元组时,领导者通常会表现得非常像额外的工作人员,从而加快查询执行速度;

相反,当计划的并行部分生成大量元组时,领导者可能几乎完全忙于读取工作人员生成的元组并执行节点级别以上的计划节点所需的任何进一步处理步骤Gather或Gather Merge节点。在这种情况下,领导者将很少执行计划的并行部分

 image.png

以上公式主要描述了优化器生成workers数量的算法依据,右边的分母部分是指查询所涉及表或索引的大小(会随着数据的变换而变化),分子部分是可修改的参数,通过参数的修改影响优化器生成workers的数量。以下内容描述了不同版本的相关参数的变化。

 

– PostgreSQL 9.6:

— min_parallel_relation_size

 

– PostgreSQL 10:

— min_parallel_table_scan_size

— min_parallel_index_scan_size

 

另外,还有对并行workers或process总数量的控制参数max_work_processer(integer)、max_parallel_workers(integer),后续内容会有并行查询相关参数说明;

 

三、PG并行查询使用先决条件

在确定使用并行技术之前,要确定软硬件的一些先决条件: 

 

1)任务task必要条件:备选进行并行操作的任务task必须是一个大任务作业,比如,长时间的查询。任务时间通常可以以分钟、小时进行计数,这样的任务,才值得冒险使用并行操作方案;

 

2)资源闲置条件:只有在数据库服务器资源存在闲置的时候,才可以考虑进行并行处理。如果经常性的繁忙,贸然使用并行只能加剧资源的争用。

 

并行操作最大的风险在于并行争用引起的效率不升反降。所以,要在确定两个前提之后,再进行并行规划处理。并行查询需要消耗更多的CPU、IO、内存资源,对生产环境有一定的影响。使用时应该考虑这些因素。这里也表明了并行查询更适用于OLAP 这种分析性的事务场景,提升复杂查询的执行效率。

 

四、PG并行查询版本差异

1)PG V9.6并行查询功能

并行访问方法

Seq扫描是唯一的并行访问方法

不支持并行索引,仅索引扫描和位图堆扫描

平行连接

支持并行执行NestedLoop和Hash连接

对于散列连接,每个工作进程准备它自己的哈希表拷贝

合并连接不能并行执行

平行聚合

每个工人执行部分聚合并最终确定

聚合由领导者完成

 

2)PG V10并行查询功能增强

postgresql V10 比较 V9.6 的并行功能有了进一步的加强 。

支持并行B-tree索引扫描(不支持非btree索引类型的并行索引扫描)

支持并行位图堆扫描

允许合并连接并行执行

允许不相关的子查询并行运行

提高parallel worker返回预先排序的数据

增加过程语言函数中的并行查询

 

3)PG V9.6与PG V10并行查询功能对比如下:

 image.png

4)PG V11 并行方面增强

支持并行创建索引(Parallel Index Builds)

支持并行哈希连接(Parallel Hash Joins)

并行排序、并行索引 (性能线性暴增)

并行Hash Join

并行 CREATE TABLE .. AS等

 

五、PG V10并行查询使用限制

1)系统不能运行在单用户模式下

2)查询要写任何数据或者锁定任何数据库行

3)一个查询在顶层或者 CTE 中包含了数据修改操作,不会为该查询产生并行计划。

4)查询可能在执行过程中被暂停

5)用DECLARE CURSOR创建的游标不会使用并行计划

6)一个FOR x IN query LOOP .. END LOOP形式的 PL/pgSQL 循环不会使用并行计划

7)因为当并行查询进行时,并行查询系统无法验证循环中的代码执行起来是安全的

8)使用了任何被标记为PARALLEL UNSAFE的函数的查询:大多数系统定义的函数都被标记为PARALLEL SAFE,但是用户定义的函数默认被标记为PARALLEL UNSAFE

9)该查询运行在另一个已经存在的并行查询内部

10)如果一个被并行查询调用的函数自己发出一个 SQL 查询,那么该查询将不会使用并行计划

11)事务隔离级别是可串行化

 

六、PG V10并行查询相关参数

 

参数

描述

max_work_processer(integer)

设置系统支持的最大后台进程,默认值为8,此参数调整后需要重启数据库才生效。备库需要大于主库

max_parallel_workers(integer)

系统并行查询进程,默认值为8。其值不超过max_work_processer

max_parallel_workers_per_gather(integer)

运行启用并行进程的进程数,默认值2。设置成0则禁用并行查询。

parallel_setup_cost(floating point)

优化器启动并行允许进程的成本,默认为1000

parallel_tuple_cost(floating point)

设置优化器通过并行进程处理一行数据的成本,默认是0.1

min_parallel_table_scan_size(integer)

设置开启并行的条件之一,表占用空间小于此值将不会开启并行,并行顺序扫描场景下扫描的数据大小通常等于表大小,默认值8MB

min_parallel_index_scan_size(integer)

设置开启并行的条件之一,实际上并行扫描不会扫描索引所有数据块,只是扫描索引相关数据块,默认值512kb

force_parallel_model(num)

强制开启并行,OLTP生产环境开启需要慎重,不建议开启

 

规划器考虑使用的后台工作进程最多为 max_parallel_workers_per_gather。

任何时候能够存在的后台工作者进程的总数由max_worker_processes 和max_parallel_workers限制;

 

当计划的并行部分顶部的节点 Gather Merge而不是Gather,它表示执行计划的并行部分的每个进程按排序顺序生成元组,并且领导者执行保持顺序的合并。

相反,Gather以任何顺序从工人中读取元组都很方便,破坏了可能存在的任何排序。

 

七、PG V10并行控制方式

1)Cluster级别

#在postgresql.conf配置文件中设置相关参数

 

 max_worker_processes = 8

 max_parallel_workers_per_gather = 2

 max_parallel_workers = 8

 cpu_tuple_cost = 0.01

 parallel_tuple_cost = 0.1  

 parallel_setup_cost = 1000.0

 min_parallel_table_scan_size = 8MB

 min_parallel_index_scan_size = 512kB

 force_parallel_mode = off

 

2)Session 级别

#会话级别关闭并行

set max_parallel_workers_per_gather = 0;

 

#会话级别开启并行并设置成本因子

set max_parallel_workers_per_gather =4;  

set max_parallel_workers=4;  

 

#针对某个表修改并行工作进程数 ,不通过表的大小计算并行度,而是直接告诉优化器这个表需要开启多少个并行计算单元。

alter table test_big set (parallel_workers =2);

更多详细信息请登陆【瀚高支持平台】查看

https://support.highgo.com/#/index/docContent/7a10899404271863