全部產品
Search
文件中心

PolarDB:ePQ支援分區表查詢

更新時間:Jul 06, 2024

PolarDB PostgreSQL版的ePQ支援分區表查詢功能。

背景資訊

隨著資料量的不斷增長,表的規模將會越來越大。為了方便管理和提高查詢效能,使用者一般會使用分區表,將大表拆分成多張子分區表,每張子分區表又可以進一步拆分成二級子分區表,從而形成了多級分區表。

PolarDB PostgreSQL版支援彈性跨機並行查詢,能夠利用叢集中多個計算節點提升唯讀查詢的效能。ePQ不僅能夠對普通表進行高效的跨機並行查詢,對分區表也實現了跨機並行查詢。

ePQ對分區表支援的基礎功能如下:

  • 對分區策略為Range/List/Hash的分區表進行並行掃描。

  • 對分區表進行索引掃描。

  • 對分區表進行串連查詢。

此外,ePQ還支援了部分與分區表相關的進階功能:

  • 分區裁剪。

  • 智能分區串連(Partition Wise Join)。

  • 對多級分區表進行並行查詢。

ePQ暫不支援對具有多列分區鍵的分區表進行並行查詢。

前提條件

支援的PolarDB PostgreSQL版的版本如下:

  • PostgreSQL 11(核心小版本1.1.17及以上)

  • PostgreSQL 14(核心小版本14.8.11.0及以上)

說明

您可通過如下語句查看PolarDB PostgreSQL版的核心小版本的版本號碼:

  • PostgreSQL 11

    show polar_version;
  • PostgreSQL 14

    select version();

使用指南

分區表並行查詢

  1. 建立一張分區策略為Range的分區表,並建立三個子分區。

    CREATE TABLE t1 (id INT) PARTITION BY RANGE(id);
    CREATE TABLE t1_p1 PARTITION OF t1 FOR VALUES FROM (0) TO (200);
    CREATE TABLE t1_p2 PARTITION OF t1 FOR VALUES FROM (200) TO (400);
    CREATE TABLE t1_p3 PARTITION OF t1 FOR VALUES FROM (400) TO (600);
  2. 開啟ePQ和ePQ分區表掃描功能。

    SET polar_enable_px TO ON;
    SET polar_px_enable_partition TO ON;
  3. 查看對分區表進行全表掃描的執行計畫。

    EXPLAIN (COSTS OFF) SELECT * FROM t1;
                    QUERY PLAN
    -------------------------------------------
     PX Coordinator 6:1  (slice1; segments: 6)
       ->  Append
             ->  Partial Seq Scan on t1_p1
             ->  Partial Seq Scan on t1_p2
             ->  Partial Seq Scan on t1_p3
     Optimizer: PolarDB PX Optimizer
    (6 rows)

    在上述執行計畫中,ePQ將會啟動一組進程並行掃描分區表的每一個子表。每一個掃描進程都會通過Append運算元依次掃描每一個子表的一部分資料(Partial Seq Scan),並通過Motion運算元(PX Coordinator)將所有進程的掃描結果匯聚到發起查詢的進程並返回。

分區靜態裁剪

當查詢的過濾條件中包含分區鍵時,ePQ最佳化器可以根據過濾條件對需要掃描的分區表進行裁剪,避免掃描不需要的子分區,節省系統資源,提升查詢效能。以上述t1表為例,查看以下查詢的執行計畫。

EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE id < 100;
                QUERY PLAN
-------------------------------------------
 PX Coordinator 6:1  (slice1; segments: 6)
   ->  Append
         ->  Partial Seq Scan on t1_p1
               Filter: (id < 100)
 Optimizer: PolarDB PX Optimizer
(5 rows)

由於查詢的過濾條件id < 100包含分區鍵,因此ePQ最佳化器可以根據分區表的分區邊界,在產生執行計畫時去掉不符合過濾條件的子分區(t1_p2t1_p3),只保留符合過濾條件的子分區(t1_p1)。

智能分區串連

在進行分區表之間的串連操作時,如果分區策略和邊界相同,並且串連條件為分區鍵時,ePQ最佳化器可以產生以子分區為單位進行串連的執行計畫,避免兩張分區表進行笛卡爾積式的串連,節省系統資源,提升查詢效能。

以兩張Range分區表的串連為例。

  1. 建立兩張分區策略和邊界都相同的分區表t2t3

    CREATE TABLE t2 (id INT) PARTITION BY RANGE(id);
    CREATE TABLE t2_p1 PARTITION OF t2 FOR VALUES FROM (0) TO (200);
    CREATE TABLE t2_p2 PARTITION OF t2 FOR VALUES FROM (200) TO (400);
    CREATE TABLE t2_p3 PARTITION OF t2 FOR VALUES FROM (400) TO (600);
    
    CREATE TABLE t3 (id INT) PARTITION BY RANGE(id);
    CREATE TABLE t3_p1 PARTITION OF t3 FOR VALUES FROM (0) TO (200);
    CREATE TABLE t3_p2 PARTITION OF t3 FOR VALUES FROM (200) TO (400);
    CREATE TABLE t3_p3 PARTITION OF t3 FOR VALUES FROM (400) TO (600);
  2. 開啟ePQ對分區表的支援。

    SET polar_enable_px TO ON;
    SET polar_px_enable_partition TO ON;
  3. 關閉Partition Wise join時,兩表在分區鍵上等值串連的執行計畫如下。

    SET polar_px_enable_partitionwise_join TO OFF;
    EXPLAIN (COSTS OFF) SELECT * FROM t2 JOIN t3 ON t2.id = t3.id;
                            QUERY PLAN
    -----------------------------------------------------------
     PX Coordinator 6:1  (slice1; segments: 6)
       ->  Hash Join
             Hash Cond: (t2_p1.id = t3_p1.id)
             ->  Append
                   ->  Partial Seq Scan on t2_p1
                   ->  Partial Seq Scan on t2_p2
                   ->  Partial Seq Scan on t2_p3
             ->  Hash
                   ->  PX Broadcast 6:6  (slice2; segments: 6)
                         ->  Append
                               ->  Partial Seq Scan on t3_p1
                               ->  Partial Seq Scan on t3_p2
                               ->  Partial Seq Scan on t3_p3
     Optimizer: PolarDB PX Optimizer
    (14 rows)

    從執行計畫中可以看出,執行slice1計劃分區的六個進程會分別通過Append運算元依次掃描分區表t2每一個子分區的一部分資料,並通過Motion運算元(PX Broadcast)接收來自執行slice2的六個進程廣播的t3全表資料,在本地完成雜湊串連(Hash Join)後,通過Motion運算元(PX Coordinator)匯聚結果並返回。本質上,分區表t2的每一行資料都與t3的每一行資料做了一次串連。

  4. 開啟Partition Wise join後,再次查看執行計畫。

    SET polar_px_enable_partitionwise_join TO ON;
    EXPLAIN (COSTS OFF) SELECT * FROM t2 JOIN t3 ON t2.id = t3.id;
                       QUERY PLAN
    ------------------------------------------------
     PX Coordinator 6:1  (slice1; segments: 6)
       ->  Append
             ->  Hash Join
                   Hash Cond: (t2_p1.id = t3_p1.id)
                   ->  Partial Seq Scan on t2_p1
                   ->  Hash
                         ->  Full Seq Scan on t3_p1
             ->  Hash Join
                   Hash Cond: (t2_p2.id = t3_p2.id)
                   ->  Partial Seq Scan on t2_p2
                   ->  Hash
                         ->  Full Seq Scan on t3_p2
             ->  Hash Join
                   Hash Cond: (t2_p3.id = t3_p3.id)
                   ->  Partial Seq Scan on t2_p3
                   ->  Hash
                         ->  Full Seq Scan on t3_p3
     Optimizer: PolarDB PX Optimizer
    (18 rows)

    在上述執行計畫中,執行slice1計劃分區的六個進程將通過Append運算元依次掃描分區表t2每個子分區中的一部分資料,以及分區表t3相對應子分區的全部資料,將兩份資料進行雜湊串連(Hash Join),最終通過Motion運算元(PX Coordinator)匯聚結果並返回。

    在上述執行過程中,分區表t2的每一個子分區t2_p1t2_p2t2_p3分別只與分區表t3對應的t3_p1t3_p2t3_p3做了串連,並沒有與其它不相關的分區串連,提高了效率。

多級分區表並行查詢

在多級分區表中,每級分區表的分區維度(分區鍵)可以不同:例如,一級分區表按照時間維度分區,二級分區表按照地區維度分區。當查詢SQL的過濾條件中包含每一級分區表中的分區鍵時,ePQ最佳化器支援對多級分區表進行靜態分區裁剪,從而過濾掉不需要被掃描的子分區。

如下圖所示:當查詢過濾條件WHERE date = '202201' AND region = 'beijing'中包含一級分區鍵date和二級分區鍵region時,ePQ最佳化器能夠裁剪掉所有不相關的分區,產生的執行計畫中只包含合格子分區。由此,執行器只對需要掃描的子分區進行掃描。

樣本

  1. 建立一張多級分區表。

    CREATE TABLE r1 (a INT, b TIMESTAMP) PARTITION BY RANGE (b);
    
    CREATE TABLE r1_p1 PARTITION OF r1 FOR VALUES FROM ('2000-01-01') TO ('2010-01-01') PARTITION BY RANGE (a);
    CREATE TABLE r1_p1_p1 PARTITION OF r1_p1 FOR VALUES FROM (1) TO (1000000);
    CREATE TABLE r1_p1_p2 PARTITION OF r1_p1 FOR VALUES FROM (1000000) TO (2000000);
    
    CREATE TABLE r1_p2 PARTITION OF r1 FOR VALUES FROM ('2010-01-01') TO ('2020-01-01') PARTITION BY RANGE (a);
    CREATE TABLE r1_p2_p1 PARTITION OF r1_p2 FOR VALUES FROM (1) TO (1000000);
    CREATE TABLE r1_p2_p2 PARTITION OF r1_p2 FOR VALUES FROM (1000000) TO (2000000);
  2. 開啟ePQ對分區表的支援。

    SET polar_enable_px TO ON;
    SET polar_px_enable_partition TO ON;
  3. 執行一條以兩級分區鍵作為過濾條件的SQL,並關閉ePQ的多級分區掃描功能,得到PostgreSQL內建最佳化器經過多級分區靜態裁剪後的執行計畫。

    SET polar_px_optimizer_multilevel_partitioning TO OFF;
    EXPLAIN (COSTS OFF) SELECT * FROM r1 WHERE a < 1000000 AND b < '2009-01-01 00:00:00';
                                           QUERY PLAN
    ----------------------------------------------------------------------------------------
     Seq Scan on r1_p1_p1 r1
       Filter: ((a < 1000000) AND (b < '2009-01-01 00:00:00'::timestamp without time zone))
    (2 rows)
  4. 開啟ePQ的多級分區掃描功能,再次查看執行計畫。

    SET polar_px_optimizer_multilevel_partitioning TO ON;
    EXPLAIN (COSTS OFF) SELECT * FROM r1 WHERE a < 1000000 AND b < '2009-01-01 00:00:00';
                                                 QUERY PLAN
    ----------------------------------------------------------------------------------------------------
     PX Coordinator 6:1  (slice1; segments: 6)
       ->  Append
             ->  Partial Seq Scan on r1_p1_p1
                   Filter: ((a < 1000000) AND (b < '2009-01-01 00:00:00'::timestamp without time zone))
     Optimizer: PolarDB PX Optimizer
    (5 rows)

    在上述計劃中,ePQ最佳化器進行了對多級分區表的靜態裁剪。執行slice1計劃分區的六個進程只需對符合過濾條件的子分區r1_p1_p1進行並行掃描(Partial Seq Scan),並將掃描到的資料通過Motion運算元(PX Coordinator)匯聚並返回。