Hologres的动态分区功能无需预先设定所有分区信息,可依据创建分区表时配置的动态分区规则,自动创建并管理分区子表。同时,还支持将符合条件的分区数据迁移到低频存储设备,在保证查询性能的同时,有效降低存储费用。
功能介绍
动态分区功能各版本支持情况如下:
Hologres V1.3版本开始,支持配置动态分区规则,系统会根据已配置的规则定期运行调度任务,提前创建分区子表和删除过期分区子表。
Hologres V1.3.37版本开始,支持动态管理冷热数据分层存储,来实现数据自动降冷,降低存储成本,详情请参见数据分层存储。
Holgores V2.1.11版本开始,动态分区支持Date类型做分区键。
Hologres V2.2版本开始,支持通过动态分区配置表中的
schd_start_time
属性来自定义分区调度时间,即自定义设置分区表创建、删除、转冷的时间。
使用限制
Hologres暂不支持插入数据至分区表父表,只支持插入数据至具体的分区表子表。
说明实时计算Flink版支持实时写入数据至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 | 否 | 是否启用动态分区管理,取值说明如下:
| 是 |
auto_partitioning.time_unit | 是 | 动态分区的时间单位,取值说明如下:
例如配置为DAY,则将按天进行分区的预创建、删除。 | 否 |
auto_partitioning.time_zone | 否 | 动态分区时区设置,默认值为当前连接的时区。配置后将按照对应时区时间点进行动态分区管理。 您可以使用如下SQL查看可选的时区和offset等。返回结果中的name列即为timezone值,例如Asia/Shanghai。
| 否 |
auto_partitioning.num_precreate | 否 | 预创建分区的数量,取值说明如下:
说明 以当前时间为2022-01-10为例, 重要 预创建分区行为会影响MAX_PT函数的行为,请配置前检查是否依赖MAX_PT函数。 | 是 |
auto_partitioning.num_retention | 否 | 保留历史分区数量,取值说明如下:
可通过 说明 以当前时间为2022-01-10为例, | 是 |
auto_partitioning.num_hot | 否 | 保留热分区数量,取值说明如下:
| |
auto_partitioning.schd_start_time | 否 | 自定义分区调度时间,当 |
表名生成规则
动态分区表时间单位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版本起支持的语法示例
创建分区表
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分钟内被创建,请稍后查看。