全部產品
Search
文件中心

Hologres:動態分區管理

更新時間:Jun 30, 2024

Hologres的動態資料分割函數無需預先設定所有分區資訊,可依據建立分區表時配置的動態分區規則,自動建立並管理分區子表。同時,還支援將合格分區資料移轉到低頻存放裝置,在保證查詢效能的同時,有效降低儲存費用。

功能介紹

動態資料分割函數各版本支援情況如下:

  • Hologres V1.3版本開始,支援配置動態分區規則,系統會根據已配置的規則定期運行調度任務,提前建立分區子表和刪除到期分區子表。

  • Hologres V1.3.37版本開始,支援動態管理冷熱資料階層式存放區,來實現資料自動降冷,降低儲存成本,詳情請參見資料階層式存放區

  • Holgores V2.1.11版本開始,動態分區支援Date類型做分區鍵。

  • Hologres V2.2版本開始,支援通過動態分區配置表中的schd_start_time屬性來自訂分區調度時間,即自訂設定分區表建立、刪除、轉冷的時間。

使用限制

  • Hologres暫不支援插入資料至分區表父表,只支援插入資料至具體的分區表子表。

    說明

    Realtime ComputeFlink版支援即時寫入資料至Hologres的分區表父表,詳情請參見即時寫入資料至Hologres的分區結果表

  • 一個分區規則只能建立一個分區表。

  • PARTITION BY類型僅支援LIST分區,切分PARTITION BY LIST只能取唯一值。

  • 若是表有主鍵,分區鍵必須是主鍵的一個子集。

  • 動態分區能力僅支援對分區父表設定調度時間(schd_start_time),不支援對分區子表設定。

配置動態分區

文法說明

動態分區管理配置既支援在建立分區表時配置動態分區管理屬性,也支援在建表後修改動態分區管理屬性,文法如下所示。

  • V2.1版本起支援的文法:

    • 建立分區表時,配置動態分區管理屬性

      -- 建立分區表時配置動態分區管理屬性
      CREATE TABLE [if not exists] [<schema_name>.]<table_name>  ([
        {
         <column_name> <column_type> [ <column_constraints>, [...]]
         | <table_constraints>
         [, ...]
        }
      ])
      PARTITION BY LIST(<column_name>)
      WITH (
         auto_partitioning_enable = 'xxx',
         auto_partitioning_time_unit = 'xxx',
         auto_partitioning_time_zone = 'xxx',
         auto_partitioning_num_precreate = 'xxx',
         auto_partitioning_num_retention = 'xxx',
         auto_partitioning_num_hot='xxx',
         auto_partitioning_schd_start_time = 'xxx'
      );
    • 建立分區表後,修改動態分區管理屬性

      -- 修改動態分區管理屬性
      ALTER TABLE [<schema_name>.]<table_name> SET (
         auto_partitioning_enable = 'xxx',
         auto_partitioning_time_unit = 'xxx',
         auto_partitioning_time_zone = 'xxx',
         auto_partitioning_num_precreate = 'xxx',
         auto_partitioning_num_retention = 'xxx',
         auto_partitioning_num_hot='xxx',
         auto_partitioning_schd_start_time = 'xxx'
      );
      
  • 所有版本支援的文法:

    • 建立分區表時,配置動態分區管理屬性

      -- 建立分區表時配置動態分區管理屬性
      BEGIN;
      CREATE TABLE [if not exists] [<schema_name>.]<table_name>  ([
        {
         <column_name> <column_type> [ <column_constraints>, [...]]
         | <table_constraints>
         [, ...]
        }
      ])
      PARTITION BY LIST(<column_name>);
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.enable', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.time_unit', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.time_zone', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.num_precreate', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.num_retention', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.num_retention', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.num_hot', 'xxx');
      CALL set_table_property ('[<schema_name>.]<table_name>', 'auto_partitioning.schd_start_time', 'xxx');
      COMMIT;
    • 建立分區表後,修改動態分區管理屬性

      -- 修改動態分區管理屬性
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.enable', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.num_precreate', 'xxx');
      CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.num_retention', 'xxx');

參數說明

重要

使用CREATE TABLE WITH文法配置動態分區時,需要將參數名中的.改為_。例如在Hologres V2.1版本中使用CREATE TABLE WITH文法配置動態分區時,auto_partitioning.enable參數名需改為auto_partitioning_enable

參數

是否必選

說明

是否可更新

auto_partitioning.enable

是否啟用動態分區管理,取值說明如下:

  • true:啟用動態分區管理。

  • false(預設值):關閉動態分區管理。

auto_partitioning.time_unit

動態分區的時間單位,取值說明如下:

  • HOUR

  • DAY

  • MONTH

  • QUARTER

  • YEAR

例如配置為DAY,則將按天進行分區的預建立、刪除。

auto_partitioning.time_zone

動態分區時區設定,預設值為當前串連的時區。配置後將按照對應時區時間點進行動態分區管理。

您可以使用如下SQL查看可選的時區和offset等。返回結果中的name列即為timezone值,例如Asia/Shanghai。

SELECT * FROM pg_timezone_names;

auto_partitioning.num_precreate

預建立分區的數量,取值說明如下:

  • 0:不進行預建立。

  • [1, 512]:以目前時間點為基準建立分區,建議該值需要大於等於2,預設值為4。

說明

以目前時間為2022-01-10為例,time_unit = DAY,num_precreate = 3 參數配置即表示將建立2022-01-10、2022-01-11、2022-01-12三個分區。

重要

預建立分區行為會影響最大分區函數函數的行為,請配置前檢查是否依賴MAX_PT函數。

auto_partitioning.num_retention

保留歷史分區數量,取值說明如下:

  • 0:不保留歷史分區。

  • -1(預設值):不清理歷史分區。

  • 正數:保留N個歷史分區,最大值為512。

可通過set hg_experimental_auto_part_max_maintained_partitions=<value>;調整保留分區的數量,最大值為8760。

說明

以目前時間為2022-01-10為例,<time_unit = DAY,num_retention = 3> 參數配置即表示將保留 2022-01-09、2022-01-08 、2022-01-07三個分區,早於2022-01-07的歷史分區將被刪除。

auto_partitioning.num_hot

保留熱分區數量,取值說明如下:

  • 0:不保留熱分區。

  • -1(預設值):不清理熱分區。

  • 正數:保留N個熱分區,最大值為512。

auto_partitioning.schd_start_time

自訂分區調度時間,當auto_partitioning.time_unit取值為HOUR時,分區調度時間預設為每個整點,若取其他值時,預設為當天的00:00:01。

表名建置規則

動態分區表時間單位auto_partitioning.time_unit取值為HOUR、DAY、MONTH、QUARTER、YEAR,動態分區將使用分區父表名加上時間尾碼作為新建立分區的表名。格式如:{parent_table}_{time_suffix}, 其中時間尾碼將依據自動分區的調度時間和時間單位對應的格式模板產生。具體的對應關係如下。

時間單位

時間尾碼格式

樣本

執行時間

HOUR

YYYYMMDDHH24

2022030117。

每個整點的開始,例如2022年3月1日 01:00:01執行任務。

DAY

YYYYMMDD

20220301。

每天00:00:01開始,例如2022年3月1日 00:00:01。

MONTH

YYYYMM

202203。

每個月的第一天00:00:01開始,例如2022年3月1日的00:00:01、2022年4月1日的00:00:01。

QUARTER

YYYYQ

20221、20222、20223、20224分別表示2022年的四個季度。

每個季度的第一天00:00:01開始,例如2022年1月1日 00:00:01。

YEAR

YYYY

2022、2023分別表示2022年、2023年的分區。

每年的第一天00:00:01開始,例如2022年1月1日 00:00:01。

使用樣本

以天(DAY)為時間單位,預先建立未來3天的分區,保留近2天的歷史分區,並將時區設定為Asia/Shanghai的程式碼範例如下。

V2.1版本起支援的文法樣本

  1. 建立分區表tbl1

    -- 2.1版本建立分區表,並配置動態分區管理:
    
    CREATE TABLE tbl1 (
        c1 text NOT NULL,
        c2 text 
    )
    PARTITION BY LIST (c2)
    WITH (
       auto_partitioning_enable = 'true',
       auto_partitioning_time_unit = 'DAY',
       auto_partitioning_time_zone = 'Asia/Shanghai',
       auto_partitioning_num_precreate = '3',
       auto_partitioning_num_retention = '2'
    );
    
  2. 待子分區產生後插入資料。

    INSERT INTO tbl1 (c1, c2) VALUES ('Data 1', '20231212');
    INSERT INTO tbl1 (c1, c2) VALUES ('Data 2', '20231213');
    INSERT INTO tbl1 (c1, c2) VALUES ('Data 3', '20231214');
  3. 查詢資料。

    SELECT * FROM tbl1 WHERE c2='20231212';

    返回結果如下:

    c1	     c2
    Data 1   20231212

所有版本支援的文法

  1. 建立分區表tbl1

    -- 建立分區表,並配置動態分區管理:
    BEGIN;
    CREATE TABLE tbl1 (
        c1 text NOT NULL,
        c2 text 
    )
    PARTITION BY LIST (c2);
    CALL set_table_property ('tbl1', 'auto_partitioning.enable', 'true');
    CALL set_table_property ('tbl1', 'auto_partitioning.time_unit', 'DAY');
    CALL set_table_property ('tbl1', 'auto_partitioning.time_zone', 'Asia/Shanghai');
    CALL set_table_property ('tbl1', 'auto_partitioning.num_precreate', '3');
    CALL set_table_property ('tbl1', 'auto_partitioning.num_retention', '2');
    COMMIT;
  2. 待子分區產生後插入資料。

    INSERT INTO tbl1 (c1, c2) VALUES ('Data 1', '20231212');
    INSERT INTO tbl1 (c1, c2) VALUES ('Data 2', '20231213');
    INSERT INTO tbl1 (c1, c2) VALUES ('Data 3', '20231214');
  3. 查詢資料。

    SELECT * FROM tbl1 WHERE c2='20231212';

    返回結果如下:

    c1	     c2
    Data 1   20231212

分區增減的邏輯如下:

時間

事件

結果

2023-12-12 09:00:00

執行如上SQL,建立分區表。

  • 建立分區父表:tbl1

  • 建立分區子表:tbl1_20231212、tbl1_20231213、tbl1_20231214

2023-12-13 00:00:00

系統自動建立分區子表。

  • 建立分區子表:tbl1_20231215

2023-12-14 00:00:00

系統自動建立分區子表。

  • 系統建立分區子表:tbl1_20231216

2023-12-15 00:00:00

系統自動建立分區子表,並清理分區子表。

  • 建立分區子表:tbl1_20231217

  • 清理分區子表:tbl1_20231212

2023-12-16 00:00:00

系統自動建立分區子表,並清理分區子表。

  • 建立分區子表:tbl1_20231218

  • 清理分區子表:tbl1_20231213

常見情境

保留指定分區子表

預設情況下,系統會按照已配置的動態分區規則,自動建立和刪除分區子表,不在保留範圍內的分區子表將被自動刪除。但在某些特殊情境中(例如在電商情境中,需要保留曆年雙11資料進行同環比分析),可能需要保留重要分區的資料,您可以通過給表增加keep_alive屬性的方式,保留指定分區子表。使用文法介紹如下。

  • V2.1版本起支援的文法:

    -- 增加保留分區
    ALTER TABLE [<schema_name>.]<table_name> SET (keep_alive = 'true');
    
    -- 刪除保留分區:刪除保留屬性後,動態分區管理會立即觸發到期資料清理
    ALTER TABLE [<schema_name>.]<table_name> SET (keep_alive = 'false');
    
  • 所有版本支援的文法:

    -- 增加保留分區
    call set_table_property('[<schema_name>.]<table_name>', 'keep_alive', 'true');
    
    -- 刪除保留分區:刪除保留屬性後,動態分區管理會立即觸發到期資料清理
    call set_table_property('[<schema_name>.]<table_name>', 'keep_alive', 'false');

動態管理分區表的儲存介質

在處理分區表時,採用冷熱階層式存放區能夠有效地平衡成本和效能。例如,可以動態保留最近N個歷史分區在熱儲存以滿足頻繁的查詢需求,而之後M個分區則可以儲存在冷層以節約成本。在刪除超過N和M分區資料的同時,結合動態管理分區的功能,可以實現此應用情境。

建立動態分區表

樣本:設定每天一個分區,動態保留最近7個歷史分區在熱儲存介質,超過7天之後的23個分區在冷儲存介質,同時刪除超過該範圍的分區建立,程式碼範例如下。

BEGIN;
CREATE TABLE tbl2(	
  c1 text not null, 
  c2 text
)
PARTITION BY LIST(c2);
CALL set_table_property('tbl2', 'auto_partitioning.enable', 'true');
CALL set_table_property('tbl2', 'auto_partitioning.time_unit', 'DAY');
CALL set_table_property('tbl2', 'auto_partitioning.num_precreate', '3');
CALL set_table_property('tbl2', 'auto_partitioning.num_hot', '7');
CALL set_table_property('tbl2', 'auto_partitioning.num_retention', '30');
COMMIT;

效果如下圖所示:

效果

修改儲存策略

您可通過修改auto_partitioning.num_hot參數值,修改熱儲存介質的分區策略。需要注意的是,如果修改該策略,已經置為冷存的分區子表,不會自動變為熱存。若現在是2022年7月1日,建立如下分區表。

BEGIN;
CREATE TABLE tbl_p(
  c1 text not null,
  c2 text
)
PARTITION BY LIST(c2);
CALL set_table_property('tbl_p', 'auto_partitioning.enable', 'true');
CALL set_table_property('tbl_p', 'auto_partitioning.time_unit', 'DAY');
CALL set_table_property('tbl_p', 'auto_partitioning.num_precreate', '3');
CALL set_table_property('tbl_p', 'auto_partitioning.num_hot', '3');
CALL set_table_property('tbl_p', 'auto_partitioning.num_retention', '10');
COMMIT;

此時的資料分布情況有如下兩種情境:

  • 情境一:擴大使用熱儲存截止的分區策略

    如果需要將動態管理原則的熱分區策略改為4個,則使用如下代碼:

    CALL set_table_property('tbl_p', 'auto_partitioning.num_hot', '4');

    由於已經置為冷存的分區子表,不會自動的變為熱存,則更改後的效果如下圖所示:樣本

  • 情境二:減小使用熱儲存截止的分區策略

    如果需要將動態管理原則的熱分區策略改為2個,則使用如下代碼:

    CALL set_table_property('tbl_p', 'auto_partitioning.num_hot', '2');

    由於已經置為冷存的分區子表,不會自動的變為熱存,但是需要從熱存變為冷存的資料會被遷移到冷存,則更改後的效果如下圖所示:樣本

將冷存分區表改為動態分區表

例如您需要將一張冷存屬性的分區表,改為動態分區表且近7天分區設定為熱存,可使用如下方法。

  1. 資料準備。

    -- 建表時指定儲存策略為冷儲存介質
    BEGIN;
    CREATE TABLE tbl2(	
      c1 text not null, 
      c2 text
    )
    PARTITION BY LIST(c2);
    CALL set_table_property('tbl2', 'storage_mode', 'cold');
    create table tbl2_20230808 partition of tbl2 for values in('20230808');
    create table tbl2_20230809 partition of tbl2 for values in('20230809');
    create table tbl2_20230810 partition of tbl2 for values in('20230810');
    create table tbl2_20230817 partition of tbl2 for values in('20230817');
    COMMIT;
  2. 修改動態分區表且將近7天分區設定為熱儲存。

    begin;
    CALL set_table_property('tbl2', 'storage_mode', 'hot'); --設定父表為hot
    CALL set_table_property('tbl2_20230810', 'storage_mode', 'cold'); --設定不需要轉熱的分區為cold
    CALL set_table_property('tbl2_20230809', 'storage_mode', 'cold');
    CALL set_table_property('tbl2_20230808', 'storage_mode', 'cold');
    CALL set_table_property('tbl2', 'auto_partitioning.enable', 'true');
    CALL set_table_property('tbl2', 'auto_partitioning.time_unit', 'DAY');
    CALL set_table_property('tbl2', 'auto_partitioning.num_precreate', '3');
    CALL set_table_property('tbl2', 'auto_partitioning.num_hot', '7');
    CALL set_table_property('tbl2', 'auto_partitioning.num_retention', '10');
    commit;

查看配置動態分區配置和調度情況

您可以通過如下SQL,查詢當前資料庫中配置了動態分區表資訊和動態分區配置資訊。

SELECT
    nsp_name AS schema_name,
    tbl_name AS table_name,
    ENABLE,
    time_unit,
    time_zone,
    num_precreate,
    num_retention,
    b.usename AS create_user,
    cret_time,
    schd_start_time,
    options
FROM
    hologres.hg_partitioning_config AS a
    LEFT JOIN pg_user AS b ON a.cret_user = b.usesysid;

以上欄位名稱介紹如下。

欄位名稱

說明

schema_name

schema名稱。

table_name

表名稱。

ENABLE

是否啟用動態分區管理。

time_unit

動態分區的時間單位。

time_zone

動態分區時區設定。

num_precreate

預建立分區數量。

num_retention

保留歷史分區數量。

create_user

建立使用者。

cret_time

建立時間。

schd_start_time

最近一次計劃調度時間。

查詢結果如下。

image

查看建立和清除分區子表日誌

Query Log中不記錄建立和清除分區子表的日誌,您可以使用如下SQL查詢建立和清除分區子表日誌。

SELECT                           
    relname,
    relowner,
    schdtime,
    trigtime,
    status,
    message,
    precreate,
    discard
FROM
    hologres.hg_partitioning_log 

以上欄位名稱介紹如下。

欄位名稱

說明

relname

schema.table

relowner

分區表的Owner。

schdtime

計劃調度時間。

trigtime

實際觸發時間。

status

狀態。

message

備忘。

precreate

建立的分區子表名。

discard

清理的分區子表名。

查詢結果如下。

image

常見問題

對於存量分區表如何開啟動態分區?

對於存量分區表您可以使用如下SQL開啟動態分區。

-- Hologres V2.1版本SQL樣本
ALTER TABLE auto_part_old SET (
   auto_partitioning_enable = 'true',
   auto_partitioning_time_unit = 'HOUR',
   auto_partitioning_time_zone = 'PRC',
   auto_partitioning_num_precreate = '4',
   auto_partitioning_num_retention = '-1',
   auto_partitioning_num_hot = '-1'
);

-- Hologres所有版本SQL樣本
BEGIN;
CALL set_table_property('auto_part_old', 'auto_partitioning.enable', 'true');
CALL set_table_property('auto_part_old', 'auto_partitioning.time_unit', 'HOUR');
CALL set_table_property('auto_part_old', 'auto_partitioning.time_zone', 'PRC');
CALL set_table_property('auto_part_old', 'auto_partitioning.num_precreate', '4');
CALL set_table_property('auto_part_old', 'auto_partitioning.num_retention', '-1');
CALL set_table_property('auto_part_old', 'auto_partitioning.num_hot', '-1');
COMMIT;
重要

auto_partitioning.time_unitauto_partitioning.time_zone為動態資料分割函數的核心配置,Hologres升級後僅允許設定一次,設定後不能再更改。

存量分區表開啟動態分區後,歷史存在的分區子表是否會收到自動清理邏輯的影響?

系統根據分區子表的名稱進行分區子表清理,若分區子表的名稱滿足{parent_table}_{time_suffix}命名規則,將會被清理,如果不滿足則不會被清理。

建立動態分區指定了num_precreate為3,執行完SQL後父表建立成功,但並沒有建立三個分區子表?

對於首次建立動態分區的任務,系統預設每10分鐘檢查一次,因此分區子表會在10分鐘內被建立,請稍後查看。