ePQ提供的自适应扫描模式可以帮助您解决计算资源不足的问题。
前提条件
支持的PolarDB PostgreSQL版的版本如下:
PostgreSQL 11(内核小版本1.1.17及以上)
PostgreSQL 14(内核小版本14.6.6.0及以上)
您可通过如下语句查看PolarDB PostgreSQL版的内核小版本的版本号:
PostgreSQL 11
show polar_version;
PostgreSQL 14
select version();
简介
PolarDB PostgreSQL版支持ePQ特性,通过利用集群中多个节点的计算能力,来实现跨节点的并行查询功能。ePQ可以支持顺序扫描、索引扫描等多种物理算子的跨节点并行化。其中,对顺序扫描算子,ePQ提供了两种扫描模式,分别为自适应扫描模式和非自适应扫描模式。
非自适应扫描。
非自适应扫描模式是ePQ顺序扫描算子(Sequential Scan)的默认扫描方式。每一个参与并行查询的PX Worker在执行过程中都会被分配一个唯一的Worker ID。非自适应扫描模式会依据Worker ID划分数据表在物理存储上的Disk Unit ID,从而实现每个PX Worker都可以均匀扫描数据表在共享存储上的存储单元,所有PX Worker的扫描结果最终会汇总形成全量的数据。
说明在非自适应扫描模式下,扫描单元会均匀划分给每个PX Worker。当存在个别只读节点计算资源不足的情况时,可能会导致:扫描过程发生计算倾斜、用户发起的单次并行查询迟迟不能完成、查询受限于计算资源不足的节点长时间不能完成扫描任务。
自适应扫描。
ePQ提供的自适应扫描模式可以解决由于计算资源不足带来的计算倾斜问题。自适应扫描模式不再限定每个PX Worker扫描特定的Disk Unit ID,而是采用请求-响应(Request-Response)模式。这种模式通过QC进程与PX Worker进程之间特定的RPC通信机制,由QC进程负责告知每个PX Worker进程可以执行的扫描任务,从而消除计算倾斜的问题。
术语
QC(Query Coordinator):发起ePQ并行查询的进程角色。
PX Worker:参与ePQ跨节点并行查询的工作进程角色。
Worker ID:唯一标识一个PX Worker的编号。
Disk Unit ID:ePQ跨节点并行扫描的最小存储单元,默认为4 MB大小。
原理介绍
非自适应扫描。
QC进程在发起并行查询任务时,会为每个PX Worker进程分配固定的Worker ID,每个PX Worker进程根据Worker ID对存储单元取模,只扫描其所属的特定的Dist Unit。具体过程如下图所示:
自适应扫描。
过程简介。
QC进程在发起并行查询任务时,会启动自适应扫描线程,用于接收并处理来自PX Worker进程的请求消息。自适应扫描线程维护了当前查询扫描任务的进度,并根据每个PX Worker进程的工作进度,向PX Worker进程分派需要扫描的Disk Unit ID。对于需要扫描的最后一个Disk Unit,自适应扫描线程会唤醒处于空闲状态的PX Worker,加速最后一块Disk Unit的扫描过程。具体过程如下图所示:
优势介绍。
消息通信机制。
由于自适应扫描线程与各个PX worker进程之间的通信数据很少,频率不高,所以重用了已有的QC进程与PX worker进程之间的libpq连接进行报文通信。自适应扫描线程通过poll的方式在需要时同步轮询PX Worker进程的请求和响应。
扫描任务协调。
PX Worker进程在执行顺序扫描算子时,会首先向QC进程发起询问请求,并将以下信息发送给QC端的自适应扫描线程。
扫描任务的编号。
扫描动作(正向 / 反向扫描)。
扫描物理块数。
说明自适应扫描线程在收到询问请求后,会创建扫描任务或更新扫描任务的进度。
可变颗粒度。
为了减少请求带来的网络交互次数,ePQ实现了可变的任务颗粒度。当扫描任务量剩余较多时,PX Worker进程单次领取的扫描物理块数较多;当扫描任务量剩余较少时,PX Worker进程单次领取的扫描物理块数相应减少。通过这种方法,可以平衡网络开销与负载均衡两者之间的关系。
缓存友好。
自适应扫描模式会尽量保证每个节点在多次执行并行查询任务时,能够重用Shared Buffer缓存,避免缓存频繁更新、淘汰。在实现上,自适应扫描模式会根据集群拓扑视图配置的节点IP地址信息,采用缓存绑定策略,尽量让同一个物理Page被同一个节点复用。
报文设计。
PX Worker请求报文:采用libpq的‘S’协议进行通信,按照key-value的方式编码为字符串。报文参数说明如下:
参数
说明
task_id
扫描任务的编号。
direction
扫描方向。
page_count
需扫描的总物理块数。
scan_start
扫描起始的物理块号。
current_page
当前扫描的物理块号。
scan_round
扫描的次数。
自适应扫描线程回复报文。
参数
说明
success
是否成功。返回true表示成功;返回false表示失败。
page_start
响应的起始物理块号。
page_end
响应的结束物理块号。
使用指南
创建测试表。
CREATE TABLE t(id INT); CREATE TABLE INSERT INTO t VALUES(generate_series(1,100)); INSERT 0 100
非自适应扫描。
开启跨机并行查询功能。
SET polar_enable_px = 1;
设置单节点并发度为3。
SET polar_px_dop_per_node = 3;
查询自适应扫描模式是否开启。
SHOW polar_px_enable_adps;
查询结果如下:
polar_px_enable_adps ---------------------- off
说明自适应扫描模式未开启。
通过
EXPLAIN
语句查看执行计划。EXPLAIN SELECT * FROM t; SELECT COUNT(*) FROM t;
结果如下:
QUERY PLAN ------------------------------------------------------------------------------- PX Coordinator 6:1 (slice1; segments: 6) (cost=0.00..431.00 rows=1 width=4) -> Partial Seq Scan on t (cost=0.00..431.00 rows=1 width=4) Optimizer: PolarDB PX Optimizer (3 rows)
说明执行计划来自ePQ优化器。
由于参与测试的只读节点有两个,所以从执行计划中可以看到整体并发度为6。
自适应扫描。
开启跨机并行查询功能。
SET polar_enable_px = 1;
设置单节点并发度为3。
SET polar_px_dop_per_node = 3;
开启自适应扫描模式开关。
SET polar_px_enable_adps = 1;
查询自适应扫描模式是否开启。
SHOW polar_px_enable_adps;
查询结果如下:
polar_px_enable_adps ---------------------- on (1 row)
说明自适应扫描模式已开启。
开启自适应扫描analyze功能。
SET polar_px_enable_adps_explain_analyze = 1;
查询自适应扫描analyze功能是否开启。
SHOW polar_px_enable_adps_explain_analyze;
查询结果如下:
polar_px_enable_adps_explain_analyze -------------------------------------- on (1 row)
说明自适应扫描analyze功能已开启。
通过
EXPLAIN ANALYZE
语句查看每个PX Worker进程扫描的物理块号。EXPLAIN ANALYZE SELECT * FROM t; SELECT COUNT(*) FROM t;
结果如下:
QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- PX Coordinator 6:1 (slice1; segments: 6) (cost=0.00..431.00 rows=1 width=4) (actual time=0.968..0.982 rows=100 loops=1) -> Partial Seq Scan on t (cost=0.00..431.00 rows=1 width=4) (actual time=0.380..0.435 rows=100 loops=1) Dynamic Pages Per Worker: [1] Planning Time: 5.571 ms Optimizer: PolarDB PX Optimizer (slice0) Executor memory: 23K bytes. (slice1) Executor memory: 14K bytes avg x 6 workers, 14K bytes max (seg0). Execution Time: 9.047 ms (8 rows)