全部產品
Search
文件中心

PolarDB:ePQ支援查看與分析執行計畫

更新時間:Jul 06, 2024

PolarDB PostgreSQL版支援ePQ查看與分析執行計畫。

背景資訊

PostgreSQL提供了EXPLAIN命令用於SQL語句的效能分析,該命令可以輸出SQL對應的查詢計劃,以及在執行過程中的具體耗時、資源消耗等資訊,可用於排查SQL的效能瓶頸。

EXPLAIN命令只適用於單機執行的SQL效能分析,PolarDB PostgreSQL版的ePQ擴充了EXPLAIN的功能,使其可以列印ePQ的跨機並存執行計劃,還可以統計ePQ執行計畫在各個運算元上的執行時間、資料掃描量、記憶體使用量等資訊,並以統一的視角提供給使用者。

前提條件

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

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

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

說明

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

  • PostgreSQL 11

    show polar_version;
  • PostgreSQL 14

    select version();

原理介紹

ePQ查詢的發起進程(QC)與背景工作處理序(Worker)之間採用libpqY協議進行通訊:

  • QC將EXPLAIN ANALYZE命令下發給Worker。

  • 各個Worker進程統計本進程內的資源使用、執行耗時等資訊。

  • 各個Worker在完成計劃分區的執行後,將統計資訊發送給QC。

  • QC等待所有Worker進程完成各自執行後,進行統計計算並輸出。

功能介紹

執行計畫查看

ePQ的執行計畫是分區的。每個計劃分區(Slice)由計算節點上的虛擬執行單元(Segment)啟動的一組進程(Gang)負責執行,完成SQL的一部分計算。ePQ在執行計畫中引入了Motion運算元,用於在執行不同計劃分區的進程組之間進行資料傳遞。因此,Motion運算元是計劃分區的邊界。

ePQ中總共引入了三種Motion運算元:

  • PX Coordinator:源端資料發送到同一個目標端(匯聚)。

  • PX Broadcast:源端資料發送到每一個目標端(廣播)。

  • PX Hash:源端資料經過雜湊計算後發送到某一個目標端(重分布)。

樣本

  • 以下為一個簡單查詢樣本:

    CREATE TABLE t (id INT);
    SET polar_enable_px TO ON;
    EXPLAIN (COSTS OFF) SELECT * FROM t LIMIT 1;
                       QUERY PLAN
    -------------------------------------------------
     Limit
       ->  PX Coordinator 6:1  (slice1; segments: 6)
             ->  Partial Seq Scan on t
     Optimizer: PolarDB PX Optimizer
    (4 rows)

    以上執行計畫以Motion運算元為界,被分為了兩個分區:一個是接收最終結果的分區slice0,一個是掃描資料的分區slice1

    對於slice1計劃分區,ePQ將使用六個執行單元(segments: 6)分別啟動一個進程來執行,這六個進程各自負責掃描表的一部分資料(Partial Seq Scan),通過Motion運算元將六個進程的資料匯聚到一個目標端(PX Coordinator 6:1),傳遞給Limit運算元。

  • 如果查詢逐漸複雜,則執行計畫中的計劃分區和Motion運算元會越來越多,樣本如下:

    CREATE TABLE t1 (a INT, b INT, c INT);
    SET polar_enable_px TO ON;
    EXPLAIN (COSTS OFF) SELECT SUM(b) FROM t1 GROUP BY a LIMIT 1;
                             QUERY PLAN
    ------------------------------------------------------------
     Limit
       ->  PX Coordinator 6:1  (slice1; segments: 6)
             ->  GroupAggregate
                   Group Key: a
                   ->  Sort
                         Sort Key: a
                         ->  PX Hash 6:6  (slice2; segments: 6)
                               Hash Key: a
                               ->  Partial Seq Scan on t1
     Optimizer: PolarDB PX Optimizer
    (10 rows)

    以上執行計畫中總共有三個計劃分區。將會有六個進程(segments: 6)負責執行slice2分區,分別掃描表的一部分資料,然後通過Motion運算元(PX Hash 6:6)將資料重分布到另外六個(segments: 6)負責執行slice1分區的進程上,各自完成排序(Sort)和彙總(GroupAggregate),最終通過Motion運算元(PX Coordinator 6:1)將資料匯聚到結果分區slice0

執行計畫分析

EXPLAIN中的ANALYZE選項會使查詢被真正執行,並收集執行過程中的各項統計資訊,而不僅僅是列印執行計畫。在ePQ的執行計畫中,同一個運算元會被一組進程執行。因此,ePQ的EXPLAIN ANALYZE需要收集執行同一個運算元的所有進程的統計資訊。

運算元層級的統計資訊如下:

  • 運算元執行時間:取執行該運算元的所有進程的最長執行時間。

  • 運算元掃描總行數:取執行該運算元的所有進程的掃描行數累加和。

  • 運算元執行次數(迴圈):取執行該運算元的所有進程的迴圈次數累加和。

  • 運算元的資源使用資訊:取執行該運算元的所有進程的資源使用量累加和。

此外,ePQ的EXPLAIN ANALYZE還可以收集執行同一運算元的各進程層級的統計資訊,可被用於判斷計劃執行過程中是否存在傾斜。具體包含資訊如下:

  • 每個進程的記憶體使用量情況。

  • 每個進程的執行時間。

  • 每個進程的處理行數。

樣本

  1. 建立一張表並插入資料。

    CREATE TABLE t2 (a INT, b INT, c VARCHAR(20));
    INSERT INTO t2 SELECT i, i*2, to_char(i, 'FM00000') FROM generate_series(1, 100000) i;
  2. 設定如下參數並執行EXPLAIN ANALYZE

    SET polar_enable_px TO ON;
    SET polar_px_enable_explain_all_stat TO ON;
    SET polar_px_explain_memory_verbosity TO detail;
    EXPLAIN (COSTS OFF, ANALYZE) SELECT * FROM t2;
                                            QUERY PLAN
    -------------------------------------------------------------------------------------------
     PX Coordinator 6:1  (slice1; segments: 6) (actual time=0.816..54.225 rows=100000 loops=1)
       Executor Memory: 9kB  Workers: 1  Max: 9kB (worker -1)
       ->  Partial Seq Scan on t2 (actual time=0.052..24.732 rows=94720 loops=1)
             Executor Memory: 326kB  Workers: 6  Max: 145kB (worker 1)
             allstat:
                 worker:0, first_time:7.396(ms), total_time:25(ms), total_num:94720
                 worker:1, first_time:7.396(ms), total_time:2.819(ms), total_num:5280
                 worker:2, first_time:7.393(ms), total_time:0.074(ms), total_num:0
                 worker:3, first_time:7.400(ms), total_time:0.078(ms), total_num:0
                 worker:4, first_time:7.402(ms), total_time:0.086(ms), total_num:0
                 worker:5, first_time:7.399(ms), total_time:0.098(ms), total_num:0
             Dynamic Pages Per Worker: [512,29]
     Planning Time: 9.768 ms
     Optimizer: PolarDB PX Optimizer
       (slice0)    Executor memory: 38K bytes.
       (slice1)    Executor memory: 68K bytes avg x 6 workers, 164K bytes max (seg1).
     Execution Time: 65.572 ms
    (17 rows)

    在上述執行計畫中:

    • 每個運算元下的Executor Memory部分列印了執行這個運算元的所有進程所使用的總記憶體量、進程數量以及使用記憶體量最大的進程編號。

    • allstat部分列印了執行運算元的每一個進程的準備時間(first_time)、執行時間(total_time)和處理元組數量(total_num)。