Hologres的動態資料分割函數無需預先設定所有分區資訊,可依據建立分區表時配置的動態分區規則,自動建立並管理分區子表。同時,還支援將合格分區資料移轉到低頻存放裝置,在保證查詢效能的同時,有效降低儲存費用。
功能介紹
動態資料分割函數各版本支援情況如下:
Hologres V1.3版本開始,支援配置動態分區規則,系統會根據已配置的規則定期運行調度任務,提前建立分區子表和刪除到期分區子表。
Hologres V1.3.37版本開始,支援動態管理冷熱資料階層式存放區,來實現資料自動降冷,降低儲存成本,詳情請參見資料階層式存放區。
Holgores V2.1.11版本開始,動態分區支援Date類型做分區鍵。
Hologres V2.2版本開始,支援通過動態分區配置表中的
schd_start_time
屬性來自訂分區調度時間,即自訂設定分區表建立、刪除、轉冷的時間。Hologres V3.0.12版本開始,新增參數
auto_partitioning_time_format
,用於指定分區鍵日期時間格式,支援指定按照YYYY-MM-DD格式建立分區。
注意事項
Hologres暫不支援插入資料至分區表父表,只支援插入資料至具體的分區表子表。
說明Realtime ComputeFlink版支援即時寫入資料至Hologres的分區表父表,詳情請參見即時寫入資料至Hologres的分區結果表。
一個分區規則只能建立一個分區表。
PARTITION BY
類型僅支援LIST
分區,切分PARTITION BY LIST
只能取唯一值。若是表有主鍵,分區鍵必須是主鍵的一個子集。
動態分區能力僅支援對分區父表設定調度時間(
schd_start_time
),不支援對分區子表設定。參數
auto_partitioning_time_format
僅支援設定一次,且一旦設定無法再次修改。對於建立表,可通過CREATE TABLE加指定參數的方式進行設定。對於存量表,可通過ALTER TABLE加指定參數的方式來配置。通過
auto_partitioning_time_format
參數指定時間格式後,分區子表命名格式與分區鍵日期格式保持一致,在查詢子表時,需要在子表名添加雙引號。例如:SELECT xxx FROM "tbl_2024_11_22"
。
配置動態分區
文法說明
動態分區管理配置既支援在建立分區表時配置動態分區管理屬性,也支援在建表後修改動態分區管理屬性,文法如下所示。
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', auto_partitioning_time_format = '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', auto_partitioning_time_format = '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'); CALL set_table_property ('[<schema_name>.]<table_name>', 'auto_partitioning.time_format', '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'); CALL set_table_property('[<schema_name>.]<table_name>', 'auto_partitioning.time_format', 'xxx');
參數說明
使用CREATE TABLE WITH
文法配置動態分區時,需要將參數名中的.
改為_
。例如在Hologres V2.1版本中使用CREATE TABLE WITH文法配置動態分區時,auto_partitioning.enable
參數名需改為auto_partitioning_enable
。
參數(V2.1以上/ALL) | 是否必選 | 說明 | 是否可更新 |
| 否 | 是否啟用動態分區管理,取值說明如下:
| 是 |
| 是 | 動態分區的時間單位,取值說明如下:
例如配置為DAY,則將按天進行分區的預建立、刪除。 | 否 |
| 否 | 動態分區時區設定,預設值為當前串連的時區。配置後將按照對應時區時間點進行動態分區管理。 您可以使用如下SQL查看可選的時區和offset等。返回結果中的name列即為timezone值,例如Asia/Shanghai。
| 否 |
| 否 | 預建立分區的數量,取值說明如下:
說明 以目前時間為2022-01-10為例, 重要 預建立分區行為會影響最大分區函數函數的行為,請配置前檢查是否依賴MAX_PT函數。 | 是 |
| 否 | 保留歷史分區數量,取值說明如下:
可通過 說明 以目前時間為2022-01-10為例, | 是 |
| 否 | 保留熱分區數量,取值說明如下:
| |
| 否 | 自訂分區調度時間,當 | |
| 否 | 建表時用來指定分區鍵的日期時間格式。
| 否 |
表名建置規則
動態分區表時間單位auto_partitioning.time_unit
取值為HOUR、DAY、MONTH、QUARTER、YEAR,動態分區將使用分區父表名加上時間尾碼作為新建立分區的表名。格式如:{parent_table}_{time_suffix}
, 其中時間尾碼將依據自動分區的調度時間和時間單位對應的格式模板產生。具體的對應關係如下。
時間單位 | 時間尾碼格式 | 樣本 | 執行時間 |
HOUR | YYYYMMDDHH24 | 2024112221。 | 每個整點的開始,例如2024年11月22日 21:00:01執行任務。 |
YYYY-MM-DD-HH24 | 2024-11-22-21。 | ||
DAY | YYYYMMDD | 20241122。 | 每天00:00:01開始,例如2024年11月22日 00:00:01。 |
YYYY-MM-DD | 2024-11-22。 | ||
MONTH | YYYYMM | 202411。 | 每個月的第一天00:00:01開始,例如2024年11月1日的00:00:01。 |
YYYY-MM | 2024-11。 | ||
QUARTER | YYYYQ | 20241、20242、20243、20244分別表示2024年的四個季度。 | 每個季度的第一天00:00:01開始,例如2024年1月1日 00:00:01。 |
YYYY-Q | 2024-1, 2024-2, 2024-3, 2024-4 分別表示2024年的四個季度。 | ||
YEAR | YYYY | 2023、2024分別表示2023年、2024年的分區。 | 每年的第一天00:00:01開始,例如2023年1月1日 00:00:01。 |
使用樣本
以天(DAY)為時間單位,預先建立未來3天的分區,保留近2天的歷史分區,並將時區設定為Asia/Shanghai
的程式碼範例如下。
V2.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' );
待子分區產生後插入資料。
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');
查詢資料。
SELECT * FROM tbl1 WHERE c2='20231212';
返回結果如下:
c1 c2 Data 1 20231212
所有版本支援的文法
建立分區表
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;
待子分區產生後插入資料。
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');
查詢資料。
SELECT * FROM tbl1 WHERE c2='20231212';
返回結果如下:
c1 c2 Data 1 20231212
分區增減的邏輯如下:
時間 | 事件 | 結果 |
2023-12-12 09:00:00 | 執行如上SQL,建立分區表。 |
|
2023-12-13 00:00:00 | 系統自動建立分區子表。 |
|
2023-12-14 00:00:00 | 系統自動建立分區子表。 |
|
2023-12-15 00:00:00 | 系統自動建立分區子表,並清理分區子表。 |
|
2023-12-16 00:00:00 | 系統自動建立分區子表,並清理分區子表。 |
|
常見情境
保留指定分區子表
預設情況下,系統會按照已配置的動態分區規則,自動建立和刪除分區子表,不在保留範圍內的分區子表將被自動刪除。但在某些特殊情境中(例如在電商情境中,需要保留曆年雙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天分區設定為熱存,可使用如下方法。
資料準備。
-- 建表時指定儲存策略為冷儲存介質 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;
修改動態分區表且將近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 | 最近一次計劃調度時間。 |
查詢結果如下。
查看建立和清除分區子表日誌
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 | 清理的分區子表名。 |
查詢結果如下。
常見問題
對於存量分區表如何開啟動態分區?
對於存量分區表您可以使用如下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_unit
和auto_partitioning.time_zone
為動態資料分割函數的核心配置,Hologres升級後僅允許設定一次,設定後不能再更改。
存量分區表開啟動態分區後,歷史存在的分區子表是否會收到自動清理邏輯的影響?
系統根據分區子表的名稱進行分區子表清理,若分區子表的名稱滿足{parent_table}_{time_suffix}
命名規則,將會被清理,如果不滿足則不會被清理。
建立動態分區指定了num_precreate
為3,執行完SQL後父表建立成功,但並沒有建立三個分區子表?
對於首次建立動態分區的任務,系統預設每10分鐘檢查一次,因此分區子表會在10分鐘內被建立,請稍後查看。