自適應(yīng)掃描
ePQ提供的自適應(yīng)掃描模式可以幫助您解決計(jì)算資源不足的問題。
前提條件
支持的PolarDB PostgreSQL版的版本如下:
PostgreSQL 11(內(nèi)核小版本1.1.17及以上)
PostgreSQL 14(內(nèi)核小版本14.6.6.0及以上)
您可通過如下語句查看PolarDB PostgreSQL版的內(nèi)核小版本的版本號:
PostgreSQL 11
show polar_version;
PostgreSQL 14
select version();
簡介
PolarDB PostgreSQL版支持ePQ特性,通過利用集群中多個(gè)節(jié)點(diǎn)的計(jì)算能力,來實(shí)現(xiàn)跨節(jié)點(diǎn)的并行查詢功能。ePQ可以支持順序掃描、索引掃描等多種物理算子的跨節(jié)點(diǎn)并行化。其中,對順序掃描算子,ePQ提供了兩種掃描模式,分別為自適應(yīng)掃描模式和非自適應(yīng)掃描模式。
非自適應(yīng)掃描。
非自適應(yīng)掃描模式是ePQ順序掃描算子(Sequential Scan)的默認(rèn)掃描方式。每一個(gè)參與并行查詢的PX Worker在執(zhí)行過程中都會被分配一個(gè)唯一的Worker ID。非自適應(yīng)掃描模式會依據(jù)Worker ID劃分?jǐn)?shù)據(jù)表在物理存儲上的Disk Unit ID,從而實(shí)現(xiàn)每個(gè)PX Worker都可以均勻掃描數(shù)據(jù)表在共享存儲上的存儲單元,所有PX Worker的掃描結(jié)果最終會匯總形成全量的數(shù)據(jù)。
說明在非自適應(yīng)掃描模式下,掃描單元會均勻劃分給每個(gè)PX Worker。當(dāng)存在個(gè)別只讀節(jié)點(diǎn)計(jì)算資源不足的情況時(shí),可能會導(dǎo)致:掃描過程發(fā)生計(jì)算傾斜、用戶發(fā)起的單次并行查詢遲遲不能完成、查詢受限于計(jì)算資源不足的節(jié)點(diǎn)長時(shí)間不能完成掃描任務(wù)。
自適應(yīng)掃描。
ePQ提供的自適應(yīng)掃描模式可以解決由于計(jì)算資源不足帶來的計(jì)算傾斜問題。自適應(yīng)掃描模式不再限定每個(gè)PX Worker掃描特定的Disk Unit ID,而是采用請求-響應(yīng)(Request-Response)模式。這種模式通過QC進(jìn)程與PX Worker進(jìn)程之間特定的RPC通信機(jī)制,由QC進(jìn)程負(fù)責(zé)告知每個(gè)PX Worker進(jìn)程可以執(zhí)行的掃描任務(wù),從而消除計(jì)算傾斜的問題。
術(shù)語
QC(Query Coordinator):發(fā)起ePQ并行查詢的進(jìn)程角色。
PX Worker:參與ePQ跨節(jié)點(diǎn)并行查詢的工作進(jìn)程角色。
Worker ID:唯一標(biāo)識一個(gè)PX Worker的編號。
Disk Unit ID:ePQ跨節(jié)點(diǎn)并行掃描的最小存儲單元,默認(rèn)為4 MB大小。
原理介紹
非自適應(yīng)掃描。
QC進(jìn)程在發(fā)起并行查詢?nèi)蝿?wù)時(shí),會為每個(gè)PX Worker進(jìn)程分配固定的Worker ID,每個(gè)PX Worker進(jìn)程根據(jù)Worker ID對存儲單元取模,只掃描其所屬的特定的Dist Unit。具體過程如下圖所示:
自適應(yīng)掃描。
過程簡介。
QC進(jìn)程在發(fā)起并行查詢?nèi)蝿?wù)時(shí),會啟動自適應(yīng)掃描線程,用于接收并處理來自PX Worker進(jìn)程的請求消息。自適應(yīng)掃描線程維護(hù)了當(dāng)前查詢掃描任務(wù)的進(jìn)度,并根據(jù)每個(gè)PX Worker進(jìn)程的工作進(jìn)度,向PX Worker進(jìn)程分派需要掃描的Disk Unit ID。對于需要掃描的最后一個(gè)Disk Unit,自適應(yīng)掃描線程會喚醒處于空閑狀態(tài)的PX Worker,加速最后一塊Disk Unit的掃描過程。具體過程如下圖所示:
優(yōu)勢介紹。
消息通信機(jī)制。
由于自適應(yīng)掃描線程與各個(gè)PX worker進(jìn)程之間的通信數(shù)據(jù)很少,頻率不高,所以重用了已有的QC進(jìn)程與PX worker進(jìn)程之間的libpq連接進(jìn)行報(bào)文通信。自適應(yīng)掃描線程通過poll的方式在需要時(shí)同步輪詢PX Worker進(jìn)程的請求和響應(yīng)。
掃描任務(wù)協(xié)調(diào)。
PX Worker進(jìn)程在執(zhí)行順序掃描算子時(shí),會首先向QC進(jìn)程發(fā)起詢問請求,并將以下信息發(fā)送給QC端的自適應(yīng)掃描線程。
掃描任務(wù)的編號。
掃描動作(正向 / 反向掃描)。
掃描物理塊數(shù)。
說明自適應(yīng)掃描線程在收到詢問請求后,會創(chuàng)建掃描任務(wù)或更新掃描任務(wù)的進(jìn)度。
可變顆粒度。
為了減少請求帶來的網(wǎng)絡(luò)交互次數(shù),ePQ實(shí)現(xiàn)了可變的任務(wù)顆粒度。當(dāng)掃描任務(wù)量剩余較多時(shí),PX Worker進(jìn)程單次領(lǐng)取的掃描物理塊數(shù)較多;當(dāng)掃描任務(wù)量剩余較少時(shí),PX Worker進(jìn)程單次領(lǐng)取的掃描物理塊數(shù)相應(yīng)減少。通過這種方法,可以平衡網(wǎng)絡(luò)開銷與負(fù)載均衡兩者之間的關(guān)系。
緩存友好。
自適應(yīng)掃描模式會盡量保證每個(gè)節(jié)點(diǎn)在多次執(zhí)行并行查詢?nèi)蝿?wù)時(shí),能夠重用Shared Buffer緩存,避免緩存頻繁更新、淘汰。在實(shí)現(xiàn)上,自適應(yīng)掃描模式會根據(jù)集群拓?fù)湟晥D配置的節(jié)點(diǎn)IP地址信息,采用緩存綁定策略,盡量讓同一個(gè)物理Page被同一個(gè)節(jié)點(diǎn)復(fù)用。
報(bào)文設(shè)計(jì)。
PX Worker請求報(bào)文:采用libpq的‘S’協(xié)議進(jìn)行通信,按照key-value的方式編碼為字符串。報(bào)文參數(shù)說明如下:
參數(shù)
說明
task_id
掃描任務(wù)的編號。
direction
掃描方向。
page_count
需掃描的總物理塊數(shù)。
scan_start
掃描起始的物理塊號。
current_page
當(dāng)前掃描的物理塊號。
scan_round
掃描的次數(shù)。
自適應(yīng)掃描線程回復(fù)報(bào)文。
參數(shù)
說明
success
是否成功。返回true表示成功;返回false表示失敗。
page_start
響應(yīng)的起始物理塊號。
page_end
響應(yīng)的結(jié)束物理塊號。
使用指南
創(chuàng)建測試表。
CREATE TABLE t(id INT); CREATE TABLE INSERT INTO t VALUES(generate_series(1,100)); INSERT 0 100
非自適應(yīng)掃描。
開啟跨機(jī)并行查詢功能。
SET polar_enable_px = 1;
設(shè)置單節(jié)點(diǎn)并發(fā)度為3。
SET polar_px_dop_per_node = 3;
查詢自適應(yīng)掃描模式是否開啟。
SHOW polar_px_enable_adps;
查詢結(jié)果如下:
polar_px_enable_adps ---------------------- off
說明自適應(yīng)掃描模式未開啟。
通過
EXPLAIN
語句查看執(zhí)行計(jì)劃。EXPLAIN SELECT * FROM t; SELECT COUNT(*) FROM t;
結(jié)果如下:
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)
說明執(zhí)行計(jì)劃來自ePQ優(yōu)化器。
由于參與測試的只讀節(jié)點(diǎn)有兩個(gè),所以從執(zhí)行計(jì)劃中可以看到整體并發(fā)度為6。
自適應(yīng)掃描。
開啟跨機(jī)并行查詢功能。
SET polar_enable_px = 1;
設(shè)置單節(jié)點(diǎn)并發(fā)度為3。
SET polar_px_dop_per_node = 3;
開啟自適應(yīng)掃描模式開關(guān)。
SET polar_px_enable_adps = 1;
查詢自適應(yīng)掃描模式是否開啟。
SHOW polar_px_enable_adps;
查詢結(jié)果如下:
polar_px_enable_adps ---------------------- on (1 row)
說明自適應(yīng)掃描模式已開啟。
開啟自適應(yīng)掃描analyze功能。
SET polar_px_enable_adps_explain_analyze = 1;
查詢自適應(yīng)掃描analyze功能是否開啟。
SHOW polar_px_enable_adps_explain_analyze;
查詢結(jié)果如下:
polar_px_enable_adps_explain_analyze -------------------------------------- on (1 row)
說明自適應(yīng)掃描analyze功能已開啟。
通過
EXPLAIN ANALYZE
語句查看每個(gè)PX Worker進(jìn)程掃描的物理塊號。EXPLAIN ANALYZE SELECT * FROM t; SELECT COUNT(*) FROM t;
結(jié)果如下:
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)