全部產品
Search
文件中心

Hologres:Fixed Plan加速SQL執行

更新時間:Aug 02, 2024

Fixed Plan是Hologres特有的執行引擎最佳化方式,本文將為您介紹可以被Fixed Plan選中的SQL需要符合的條件和參數配置。

背景資訊

Fixed Plan是Hologres特有的執行引擎最佳化方式,傳統的SQL執行要經過最佳化器、協調器、查詢引擎、儲存引擎等多個組件,而Fixed Plan選擇了短路徑(Short-Cut)最佳化執行SQL,繞過了最佳化器、協調器、部分查詢引擎的開銷。通過Fixed FrontEnd直接對接Fixed Query Engine,實現SQL執行效率的成倍提升,是支援高吞吐即時寫入,高並發查詢的關鍵最佳化方法。關於Fixed Plan的介紹請參見產品架構

在Hologres中,預設走Fixed Plan的情境如下:

  • Flink即時寫入資料至Hologres。

  • DataWorksData Integration即時寫入資料至Hologres。

  • Holo Client寫入Hologres。

其餘寫入情境可根據SQL進行一定的配置讓其走Fixed Plan,詳情請參見下文。

說明

以上情境會預設保證合格SQL走Fixed Plan,但是以上情境的SQL不一定都符合條件即不一定都能走Fixed Plan。

相關GUC參數

  • GUC列表

    以下為Fixed Plan需要用到的參數配置,所有參數取值為on或者off。所有參數已經在Holo Client中預設開啟,Session層級生效。

    GUC名稱

    適用情境

    預設值

    GUC變更記錄

    hg_experimental_enable_fixed_dispatcher

    查看執行個體的Fixed Plan是否開啟。

    支援Insert、Update、Delete、PrefixScan情境單行記錄的Fixed Plan寫入、更新、刪除、查詢。

    on

    不涉及。

    hg_experimental_enable_fixed_dispatcher_for_multi_values

    控制Insert多行記錄的Fixed Plan寫入。

    說明

    不保證原子性,即一次性寫入多條的時候,如果沒報錯就是全部正常寫入了,如果報錯了只會報一條的錯誤,有可能全部沒寫入也有可能部分寫入了部分沒寫入,沒有寫入的部分會將錯誤反饋給上層應用端,由應用端進行重試。

    on

    Hologres從V1.3.35版本開始,通過該GUC支援Insert、Update、Delete多行記錄的Fixed Plan寫入、更新、刪除。

    hg_experimental_enable_fixed_dispatcher_autofill_series

    支援含有Serial類型列的Fixed Plan寫入。建議用戶端session層級開啟。

    off

    Hologres從V1.3.25版本開始,該GUC參數的預設值為on

    hg_experimental_enable_fixed_dispatcher_for_update

    支援更新(UPDATE)情境的Fixed Plan更新。建議用戶端session層級開啟。

    off

    Hologres從V1.3.25版本開始,hg_experimental_enable_fixed_dispatcher_for_update廢棄使用,即合格UPDATE語句會預設使用Fixed Plan,但UPDATE多行記錄需要配置set hg_experimental_enable_fixed_dispatcher_for_multi_values =on

    hg_experimental_enable_fixed_dispatcher_for_delete

    支援刪除(DELETE)情境的Fixed Plan刪除。建議用戶端session層級開啟。

    off

    Hologres從V1.3.25版本開始,hg_experimental_enable_fixed_dispatcher_for_delete廢棄使用即合格DELETE語句會預設走Fixed Plan,但DELETE多行記錄需要配置set hg_experimental_enable_fixed_dispatcher_for_multi_values =on

    hg_experimental_enable_fixed_dispatcher_for_scan

    支援PrefixScan情境的Fixed Plan查詢。

    說明

    PrefixScan是指多列主鍵,查詢條件只給前面幾列主鍵。目前不支援列存表PrefixScan情境的Fixed Plan查詢。

    off

    推薦從1.3.35版本開始使用。

    hg_experimental_enable_bhclient_cache_on_session

    支援更改緩衝模式,存在以下兩種情況。

    • on:使用cached on session模式。

    • off:使用cached on fe模式。

    說明

    cached on sessioncached on fe的區別如下。

    • cached on session是每個串連擁有自己的Writer、Reader,單串連的吞吐更好,但啟動會更慢(每個表第一次進行讀或寫時需要有啟動時間)。

    • cached on fe是FE(Frontend)節點上所有串連共用Writer、Reader,串連斷開後Writer、Reader不會關閉,所以總體上沒有啟動時間。

    off

    不涉及。

    hg_experimental_disable_fixed_planner_conflict_pk_check

    控制INSERT INTO <table_name> VALUES (...) ON CONFLICT(<column>)文法中的column是否支援非主鍵欄位。

    • false:不支援。

    • true:支援。

      說明

      該GUC參數設定為true,column支援填寫非主鍵欄位,但INSERT ON CONFLICT語句實際執行時,還是按照主鍵是否重複(ON CONFLICT(pk))來處理資料。

    false

    • Hologres從V1.3至V2.1.28版本,ON CONFLICT(<column>)中的欄位必須為主鍵欄位。

    • Hologres從V2.1.29版本開始,通過該GUC參數控制ON CONFLICT(<column>)中的欄位是否支援非主鍵欄位。

  • GUC使用

    • 查看GUC是否開啟

      通過show命令查看GUC是否開啟,命令語句如下。

      SHOW <GUC_name>;

      使用樣本如下。

      -- 查看執行個體層級是否開啟Fixed Plan
      SHOW hg_experimental_enable_fixed_dispatcher;
    • 開啟GUC

      • session層級開啟GUC

        通過set命令可以在session層級設定GUC參數。session層級的參數只在當前session生效,當串連斷開之後,將會失效,建議加在SQL前一起執行,文法樣本如下。

        SET <GUC_name> = <values>;

        GUC_name為GUC參數的名稱;values為GUC參數的值。

        使用樣本如下。

        -- insert on conflict多行記錄支援Fixed Plan寫入
        SET hg_experimental_enable_fixed_dispatcher_for_multi_values =on;
      • 資料庫層級開啟GUC

        通過alter database xx set xxx命令來設定資料庫層級的GUC參數,執行完成後在整個資料庫生效,設定完成後當前串連需要重新中斷連線才會生效。建立資料庫不會生效,需要重新手動設定,文法樣本如下。

        ALTER database <db_name> SET <GUC_name> = <values>;

        db_name為資料庫名稱,GUC_name為GUC參數的名稱,values為GUC參數的值。

        使用樣本如下。

        --DB層級開啟fixed plan
        ALTER database <db_name> SET hg_experimental_enable_fixed_dispatcher =on;

資料類型要求

  • 表的每一列都不能是MONEY或MONEY ARRAY類型。

  • 進行DML(INSERT、UPDATE、DELETE)操作的列和進行SELECT(select的target列和where裡的列都要滿足)操作的列支援的類型如下。

    • BOOLEAN(別名BOOL)

    • SMALLINT

    • INTEGER(別名INT或INT4)

    • BIGINT(別名INT8)

    • FLOAT(別名FLOAT4)

    • DOUBLE PRECISION(別名FLOAT8)

    • CHAR(n)

    • VARCHAR(n)

    • BYTEA

    • JSON和JSONB

    • TEXT(別名VARCHAR)

    • TIMESTAMP WITH TIME ZONE(別名TIMESTAMPTZ)

    • DATE

    • TIMESTAMP

    • DECIMAL(別名NUMERIC)

    • ROARINGBITMAP

    • TIME(Hologres V2.2版本開始支援)

    • TIMETZ(Hologres V2.2版本開始支援)

    • 數群組類型

      • boolean[]

      • smallint[]

      • int4[]

      • int8[]

      • float4[]

      • float8[]

      • char(n)[]

      • varchar(n)[]

      • text[]

INSERT情境

  • INSERT運算式

    Fixed Plan支援以下INSERT運算式。

    -- 寫入單行
    INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..) ON conflict xxx;
    -- 寫入多行
    INSERT INTO TABLE(col1,col2,col3..) VALUES(?,?,?..),(?,?,?..) ON conflict xxx;
    說明
    • 支援使用INSERT命令寫入內部表,不支援外部表格。

    • 支援使用INSERT命令寫入分區表,Hologres V1.3及以上版本支援寫入分區父表。

  • Insert on conflict單行

    • 支援情境如下。

      • 支援沒有on conflict的運算式。

      • 支援含有on conflict do nothing的運算式。

      • 支援on conflict do update,必須更新所有insert的非PK(Primary Key,主鍵,以下簡稱PK)列,PK是否更新都可以,並且只能是col = excluded.col方式更新。Hologres V1.3及以上版本支援更新部分非PK列,但是仍僅支援col = excluded.col方式更新

    • 使用樣本如下。

      BEGIN;
      CREATE TABLE test_insert_oneline (
          pk1 int,
          pk2 int,
          col1 int,
          col2 int,
          PRIMARY KEY (pk1, pk2)
      );
      COMMIT;
      
      --update所有非PK列,可以Fixed Plan
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = excluded.col2;
      
      --update所有列(包含PK和非PK),可以Fixed Plan
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = excluded.col2, pk1 = excluded.pk1, pk2 = excluded.pk2;
      
      --必須update所有非pk的要insert的列,此例子不包含col2,僅Hologres V1.3僅以上版本支援Fixed Plan
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1;
      
      --必須是set col = excluded.col方式更新,因此不能Fixed Plan
      INSERT INTO test_insert_oneline
          VALUES (1, 2, 3, 4)
      ON CONFLICT (pk1, pk2)
          DO UPDATE SET
              col1 = excluded.col1, col2 = 5;
  • Insert on conflict多行

    • insert on conflict多行時,運算式如下。

      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO TABLE (col1, col2, col3..)
          VALUES (?, ?, ?..), (?, ?, ?..)
      ON CONFLICT xxx;
      • 需要配置GUC參數:hg_experimental_enable_fixed_dispatcher_for_multi_values=on;。Hologres從1.3.35開始,該參數預設為on

      • 不保證原子性,即一次性寫入多條的時候,如果沒報錯就是全部正常寫入了,如果報錯了有可能全部沒寫入也有可能部分寫入了部分沒寫入。

    • 寫入多行另一種寫法運算式如下。

      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO TABLE selectunnest (ARRAY[TRUE, FALSE, TRUE]::bool[]), unnest(ARRAY[1, 2, 3]::int4[]), unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT xxx;
      
      • 需要配置GUC參數:hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

      • 寫入的列不能是數群組類型。

      • unnest裡ARRAY必須顯式轉換為對應列類型的數群組類型。

      使用樣本如下。

      BEGIN;
      CREATE TABLE test_insert_multiline (
          pk1 int8,
          col1 float4,
          PRIMARY KEY (pk1)
      );
      COMMIT;
      
      --支援Fixed Plan
      SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
      
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]::int8[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT
          DO NOTHING;
      
      --unnest裡ARRAY沒有顯式cast,不支援Fixed Plan
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]),
          unnest(ARRAY[1.11, 2.222, 3])
      ON CONFLICT
          DO NOTHING;
      
      --第一列是int8,所以應該cast為int8[],這裡例子是int4[],因此不支援Fixed Plan
      INSERT INTO test_insert_multiline
      SELECT
          unnest(ARRAY[1, 2, 3]::int4[]),
          unnest(ARRAY[1.11, 2.222, 3]::float4[])
      ON CONFLICT
          DO NOTHING;
  • 局部更新情境

    Hologres支援通過主鍵,對錶的部分列更新,Fixed Plan同樣支援局部更新情境,需要滿足如下條件。

    • Insert的列需要與Update的列一一對應,包括數量和順序。

    • 只能是col = excluded.col方式更新。

  • 帶有條件判斷的Upsert

    為了應對上遊資料同PK行的亂序需求,支援類HBase CheckAndPut介面,Hologres支援帶有條件判斷的InsertUpdate語句走Fixed Plan,條件如下。

    • 插入單條資料時支援;插入多條資料時,需要設定GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

    • where條件僅支援單個非PK欄位且比較符需在=、<>、>、>=、<、<=、IS NULL、IS NOT NULL範圍內 ,可對該非PK欄位使用coalesce函數。

    使用樣本如下。

    BEGIN;
    CREATE TABLE test_check_and_insert (
        pk int,
        col int,
        scn int,
        PRIMARY KEY (pk)
    );
    COMMIT;
    
    --支援Fixed Plan
    --列已有值和常量比較
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > 0;
    
    --列已有值和寫入值比較
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > excluded.scn;
    
    --若已有值可能為null,可用coalesce
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            coalesce(old.scn, 3) > 2;
    
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            coalesce(old.scn, 3) > excluded.scn;
    
    --支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    --列已有值和常量比較
    INSERT INTO test_check_and_insert AS old
        VALUES (1, 1, 1), (2, 3, 4)
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col, scn = excluded.scn
        WHERE
            old.scn > 3;
    
    --也支援unnest寫法
    INSERT INTO test_check_and_insert AS old
    SELECT
        unnest(ARRAY[5, 6, 7]::int[]),
        unnest(ARRAY[1, 1, 1]::int[]),
        unnest(ARRAY[1, 1, 1]::int[])
    ON CONFLICT (pk)
        DO UPDATE SET
            col = excluded.col,
            scn = excluded.scn
        WHERE
            old.scn > 3;
    
  • Default列

    表中含有Default列時,可以進行Fixed Plan的條件如下。

    • 插入單條資料時支援;插入多條資料時,需要Hologres執行個體在V1.1.36及以上版本,若低於此版本請升級執行個體。同時需要設定GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

    • Hologres V1.3及以上版本支援有Default列的表insert on conflict運算式的Fixed Plan。之前版本執行個體有Default列的表,不支援insert on conflict運算式的Fixed Plan。

    使用樣本如下。

    BEGIN;
    CREATE TABLE test_insert_default (
        pk1 int,
        col1 int DEFAULT 99,
        PRIMARY KEY (pk1)
    );
    COMMIT;
    
    --支援Fixed Plan
    INSERT INTO test_insert_default (pk1)
        VALUES (1);
    
    --需要V1.1.36及以上版本支援
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    INSERT INTO test_insert_default (pk1)
        VALUES (1), (2), (3);
  • Serial列

    錶帶有自增序列Serial時,支援單條或者多條寫入進行Fixed Plan的條件如下。

    • 需要配置GUC參數:set hg_experimental_enable_fixed_dispatcher_autofill_series=on;,從Hologres V1.3.25版本開始,該GUC參數預設為on

    • 插入多條資料時,還需配置GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values=on;

    使用樣本如下。

    BEGIN;
    CREATE TABLE test_insert_serial (
        pk1 int,
        col1 serial,
        PRIMARY KEY (pk1)
    );
    COMMIT;
    
    --支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON;
    
    INSERT INTO test_insert_serial (pk1)
        VALUES (1);
    
    --支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_autofill_series = ON;
    
    SET hg_experimental_enable_fixed_dispatcher_for_multi_values = ON;
    
    INSERT INTO test_insert_serial (pk1)
        VALUES (1), (2), (3);
    

UPDATE情境

  • Update運算式

    Update時能進行Fixed Plan的運算式如下。

    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE TABLE SET col1 = ?,col2 = ? WHERE pk1 = ? AND pk2 = ?;
  • Update情境使用

    Update情境支援進行Fixed Plan的條件如下。

    • 支援更新內部表,不支援更新外部表格;支援更新分區子表,不支援更新分區父表;表必須有主鍵(PK)。

    • 需要配置GUC參數:hg_experimental_enable_fixed_dispatcher_for_update=on; 。Hologres從 V1.3.25版本開始,該參數廢棄使用,合格Update則會預設走Fixed Plan,但如果是Update更新多行時,需要配置GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values =on

    • set的列不能是主鍵(PK)。

    • where條件裡有且只能有全部的PK。

    • 可以使用pk in (?,?,?) 或 pk = ANY() 一次修改多條。樣本:pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5,改(1,3,5),(1,4,5),(2,3,5),(2,4,5)四條。

    • where條件裡同一列只能有一個條件(一模一樣的視為一個條件)。

    使用樣本如下。

    BEGIN;
    CREATE TABLE test_update (
        pk1 int,
        pk2 int,
        col1 int,
        col2 int,
        PRIMARY KEY (pk1, pk2)
    );
    COMMIT;
    
    --支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 = 3
        AND pk2 = 4;
    
    --支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1
    WHERE
        pk1 = 3
        AND pk2 = 4;
    
    --支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk2 = ANY ('{3,4}');
    
    --pk1多個過濾條件,不支援Fixed Plan
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 = 3
        AND pk1 = 4;
    
    --pk1多個過濾條件,不支援Fixed Plan
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk1 = 1;
    
    --pk1多個過濾條件,但過濾條件相同,支援Fixed Plan
    SET hg_experimental_enable_fixed_dispatcher_for_update = ON;
    
    UPDATE
        test_update
    SET
        col1 = 1,
        col2 = 2
    WHERE
        pk1 IN (1, 2)
        AND pk1 IN (1, 2)
        AND pk2 = 4;
    

DELETE情境

  • Delete運算式

    Delete時能進行Fixed Plan的運算式如下。

    SET hg_experimental_enable_fixed_dispatcher_for_delete = ON;
    
    DELETE FROM TABLE
    WHERE pk1 = ?
        AND pk2 = ?
        AND pk3 = ?;
  • Delete情境使用

    Delete情境支援進行Fixed Plan的條件如下。

    • 支援Delete內部表,不支援Delete外部表格;支援Delete分區子表,不支援Delete分區父表;表必須有主鍵(PK)。

    • 需要配置GUC參數:hg_experimental_enable_fixed_dispatcher_for_delete=on; 。Hologres從 V1.3.25版本開始,該參數廢棄使用,合格Delete則會預設走Fixed Plan,但如果是Delete多行時,需要配置GUC參數:set hg_experimental_enable_fixed_dispatcher_for_multi_values =on

    • where條件裡有且只能有全部的PK,從Hologres V1.3版本開始,支援where過濾條件的最後一個欄位為非PK欄位,該非PK欄位支援=、<>、>、>=、<、<=、IS NULL、IS NOT NULL 比較符以及使用coalesce函數。

    • 可以使用pk in (?,?,?) 或 pk = ANY() 一次刪除多條。樣本:pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5 ,刪除(1,3,5),(1,4,5),(2,3,5),(2,4,5)四條。

    • 同一列只能有一個條件(一模一樣的視為一個條件)。

    使用樣本如下。

    BEGIN;
    CREATE TABLE test_delete (
        pk1 int,
        pk2 int,
        col1 int,
        col2 int,
        PRIMARY KEY (pk1, pk2)
    );
    COMMIT;
    
    --支援Fixed Plan,更多情境與Update範例一致
    SET hg_experimental_enable_fixed_dispatcher_for_delete = ON;
    
    DELETE FROM test_delete
    WHERE pk1 = 1
        AND pk2 = 2;
    

SELECT情境

  • SELECT運算式

    SELECT時能進行Fixed Plan的運算式如下。

    SELECT
        col1,
        col2,
        col3,
    ...
    FROM
        TABLE
    WHERE
        pk1 = ?
        AND pk2 = ?
        AND pk3 = ?;
    
    • 支援Select內部表,不支援外部表格。

    • 支援分區子表,不支援分區父表。

    • 表必須有主鍵(PK)。

  • 點查(key/value)情境

    點查情境支援的情況如下。

    • where條件裡有且只能有全部的PK。

    • 可以使用pk in (?,?,?) 或 pk = ANY() 一次查多條。樣本: pk1 in (1,2) and pk2 = any('{3,4}') and pk3 = 5,查(1,3,5),(1,4,5),(2,3,5),(2,4,5)四條。

    • 同一列只能有一個條件(一模一樣的視為一個條件)。

    • 如果有limit,limit的值必須>0

    使用樣本如下。

    BEGIN;
    CREATE TABLE test_select (
        pk1 int,
        pk2 int,
        col1 int,
        col2 int,
        PRIMARY KEY (pk1, pk2)
    );
    CALL set_table_property ('test_select', 'orientation', 'row');
    COMMIT;
    
    --支援Fixed Plan
    SELECT * FROM test_select WHERE pk1 = 1 AND pk2 = 2;
  • PrefixScan情境

    • PrefixScan情境運算式

      PrefixScan情境是指表有多個主鍵,查詢時按照左匹配原則只查幾列主鍵,查詢運算式如下。

      SET hg_experimental_enable_fixed_dispatcher_for_scan = on;
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 = ?;
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 < ?;--從1.1.48版本開始支援pk最後一列條件為range
      SELECT col1,col2,col3,... FROM TABLE WHERE pk1 = ? AND pk2 BETWEEN ? AND ?;--從1.1.48版本開始支援pk最後一列條件為range                                
    • PrefixScan使用

      PrefixScan的使用條件如下。

      • 需要配置GUC參數:hg_experimental_enable_fixed_dispatcher_for_scan=on;,且執行個體在V1.3.35版本以上。

      • 表必須有Distribution Key,且where語句裡必須包含所有的Distribution Key。

      • where語句裡有且只有PK的Prefix。PrefixScan從V1.1.48版本開始支援主鍵最後一列條件設定為範圍(同時包含上限和下限)。

        說明

        Prefix定義: 若PK為(pk1,pk2,pk3),則(pk1),(pk1,pk2)為Prefix。

      • 僅行存表(包括行列共存)支援PrefixScan。

      • 同一列只能有一個條件(一模一樣的視為一個條件)。

      • 如果含有limit條件,limit的值必須大於0。

      說明

      PrefixScan一次性返回所有結果行,如果結果的位元組數大於hg_experimental_fixed_scan_bytesize_limit會報錯:scan result size larger than fixed scan size limit ,可以通過配置hg_experimental_fixed_scan_bytesize_limit參數設定更符合情境的值,預設值為1048576,即1MB。

      樣本如下,若表PK為(pk1,pk2,pk3,pk4), Distribution Key為pk1,pk3

      BEGIN;
      CREATE TABLE test_select_prefix (
          pk1 int,
          pk2 int,
          pk3 int,
          pk4 int,
          PRIMARY KEY (pk1, pk2, pk3, pk4)
      );
      CALL set_table_property ('test_select_prefix', 'orientation', 'row');
      CALL set_table_property ('test_select_prefix', 'distribution_key', 'pk1,pk3');
      COMMIT;
      
      --沒有包含所有distribution key,不能走fixed plan
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ?;
      --不是pk的prefix,不能走fixed plan
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk3 = ?;
      
      --可以走fixed plan
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_select_prefix WHERE pk1 = ? AND pk2 = ? AND pk3 = ?;
      

      可以使用pk in (?,?,?)pk = ANY()一次性查多條,命令如下。

      pk1 IN (1,2) AND pk2 = 3 <=> scan(1,3),(2,3)兩組
      pk2 =any('{3,4}') AND pk1 IN (1,2) <=> scan(1,3),(1,4),(2,3),(2,4)四組
    • 使用樣本

      BEGIN;
      CREATE TABLE test_scan (
          pk1 int,
          pk2 int,
          pk3 int,
          col1 int,
          PRIMARY KEY (pk1, pk2, pk3)
      );
      CALL set_table_property ('test_scan', 'orientation', 'row');
      CALL set_table_property ('test_scan', 'distribution_key', 'pk1,pk2');
      COMMIT;
      
      INSERT INTO test_scan
          VALUES (1, 2, 3, 4);
      
      --支援Fixed Plan
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 2;
      
      --支援Fixed Plan
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 IN (2, 3);
      
      --支援Fixed Plan
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = ANY ('{3,4}') AND pk2 IN (2, 3);
      
      --支援fixed plan,pk最後一列是range條件,需要1.1.48及以上版本支援
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 > 1 AND pk3 < 4;
      
      --支援fixed plan,pk最後一列是range條件,需要1.1.48及以上版本支援
      SET hg_experimental_enable_fixed_dispatcher_for_scan = ON;
      
      SELECT * FROM test_scan WHERE pk1 = 1 AND pk2 = 1 AND pk3 BETWEEN 1 AND 4;
      
      --不包含所有的distribution key,不支援Fixed Plan
      SELECT * FROM test_scan WHERE pk1 = 1;
      
      --不符合主鍵首碼Prefix,不支援Fixed Plan
      SELECT * FROM test_scan WHERE pk2 = 2;

COPY情境

Hologres從1.3.17版本開始,COPY語句支援走Fixed Plan,與非Fixed Plan相比差異如下。

對比項

Fixed Plan

非Fixed Plan

鎖類型

行鎖

表鎖

資料可見行

寫入即可見。

Copy命令執行結束後可見。

效能

非常高

支援類型

TEXT或BINARY

TEXT

支援的主鍵衝突策略

支援如下策略:

  • NONE:主鍵發生衝突報錯。

  • IGNORE:主鍵發生衝突則對該資料執行跳過操作。

  • UPDATE:主鍵發生衝突則對該資料執行更新操作。

NONE(衝突則報錯)

COPY語句新增如下參數。

參數

說明

stream_mode

是否走Fixed Plan,取值如下。

  • true:走Fixed Plan。

  • false:不走Fixed Plan。

on_conflict

衝突策略,取值如下:

  • NONE:主鍵發生衝突報錯。

  • IGNORE:主鍵發生衝突則對該資料執行跳過操作。

  • UPDATE:主鍵發生衝突則對該資料執行更新操作。

命令樣本如下。

COPY table_name (column0, column1, column2)
FROM
    STDIN WITH (
        format BINARY,
        stream_mode TRUE,
        on_conflict UPDATE);

非全列表現說明。

  • 如果Copy寫入的列不是全列,則為局部更新,表現如下:

    CREATE TABLE t0 (
        id int NOT NULL,
        name text,
        age int,
        PRIMARY KEY (id)
    );
    
    COPY t0 (id,
        name)
    FROM
        STDINWITH (stream_mode TRUE, on_conflict UPDATE);
    
    -- 上述COPY等價與如下
    INSERT INTOINSERT INTO t0 (id, name)
        VALUES (?, ?)
    ON CONFLICT (id)
        DO UPDATE SETid = excluded.id, name = excluded.name;
  • 如果Copy寫入的列不是全列,且未參與寫入的列設定了預設值屬性,表現如下:

    CREATE TABLE t0 (
        id int NOT NULL,
        name text,
        age int DEFAULT 0,
        PRIMARY KEY (id)
    );
    
    COPY t0 (id,
        name)
    FROM
        STDINWITH (stream_mode TRUE, on_conflict UPDATE);
    
    -- 上述COPY等價與如下INSERT INTO
    -- 若id資料不存在,age列賦值default value;
    -- 若id資料已存在,age列不更新
    INSERT INTO t0 (id, name, age)
        VALUES (?, ?, DEFAULT)
    ON CONFLICT (id)
        DO UPDATE SETid = excluded.id, name = excluded.name;
    

驗證Fixed Plan

  • 通過FixedPlan執行的更新類SQL,在控制台的即時匯入RPS面板中會顯示為SDK類型,包括INSERT、UPDATE和DELETE類型的操作。建議即時寫入類Insert、Update、Delete都盡量最佳化為Fixed Plan方案,改善資料更新的效率。RPS

  • 通過查看SQL執行計畫(explain sql),如果返回的執行計畫中含有FixedXXXNode,即表示觸發了Fixed Plan,如下圖所示。如未產生含有FixedXXXNode的執行計畫,請對照上文情境支援條件, 查看是否滿足條件。驗證fixedplan

效能調優

在某些情境上若是已經開啟Fixed Plan但還需要做效能調優時,可選擇如下方式。

  • Hologres V1.1.49版本開始針對Fixed Plan點查情境進行了最佳化,在大規模點查的情況下提升了30%以上吞吐。若有需要請升級執行個體至V1.1.49及以上版本。

  • 用戶端合理的攢批(使用Holo Client會自動攢批),即一次執行SQL命令的數量,實踐證明數量為512或者512的倍數效能會更好。

常見問題

  • 問題1:串連報錯:role/database does not exist.

    • 原因:使用者或DB不存在。

    • 解決辦法:檢查串連資訊,填寫正確的使用者名稱或DB名。

      您可以登入Hologres管理主控台,單擊目標執行個體操作列中的管理,然後單擊資料庫管理,在使用者管理 DB 授權頁面擷取並確認使用者名稱或DB名。

  • 問題2:資料寫入過程中報錯:the requested table name: xxx (id: xx, version: xx) mismatches the version of the table (id: xx, version: xx) from server.

    • 原因:資料寫入過程中表元資訊發生變化(如增加列)導致Table Version發生變化。

    • 解決方案:重建立立串連,Fixed Plan會擷取新的表元資訊並進行寫入。