Hologres V3.1版本支持逻辑分区表。相比于物理分区表,逻辑分区表可有效解决表数量过多、元数据膨胀而可能产生的稳定性问题。本文为您介绍如何将物理分区表迁移为逻辑分区表。
使用场景
针对如下场景建议您由物理分区表迁移为逻辑分区表:
Table Group下的物理分区表的子分区表数量多(例如大于10000张),元数据规模大。
每日新增分区数量多,DDL操作次数多。
迁移方案
方案一:先双写验证再迁移业务
使用该方案进行分区表迁移,能够最大程度降低对业务的影响,保证业务稳定性。流程如下:
停止原物理分区表数据导入任务,新建逻辑分区表,并完成存量数据迁移。存量数据迁移方案,详情请参见存量数据迁移。
如果表结构不需改变,且数据量适中,推荐使用CLONE语法。
如果表结构需要改变,或数据量较大、数据迁移压力大,推荐使用手动迁移方式。
对新逻辑分区表创建数据导入任务,同时启动新老分区表的数据导入任务(即双写)。
新逻辑分区表业务验证。
业务迁移,通过如下两个方式。
(推荐)将查询直接迁移到新逻辑分区表上,即修改查询任务的目标表名为新逻辑分区表名,同时按需增加分区过滤条件。
将新逻辑分区表RENAME为原物理分区表名,并修改对原物理分区子表的写入与查询任务,改为写入与查询父表并增加分区过滤条件。命令如下:
BEGIN; ALTER TABLE <source_table_name> RENAME TO <source_table_name_archive>; ALTER TABLE <target_table_name> RENAME TO <source_table_name>; COMMIT;
运维任务适配。
(不推荐)方案二:快速迁移
若您能够接受较长的变更时间窗口,并且允许部分读写任务出现失败,则可以采用REBUILD语法进行迁移。流程如下:
停止原物理分区表数据导入任务。
使用Rebuild语法完成存量数据迁移。详情请参见REBUILD语法。
修改导入任务,并启动导入任务。
查询任务适配。
运维任务适配。
分区表迁移
表结构转换
逻辑分区表与原物理分区表相比,在建表语句方面,涉及如下转换工作。
DDL需增加LOGICAL关键字,并增加分区键的NOT NULL约束。
(可选)物理分区表仅支持一个分区键,逻辑分区表支持最多两个分区键,您可根据需要增加分区键数量。
示例如下。
创建物理分区表:
BEGIN; CREATE TABLE user_profile ( a TEXT, b TEXT, ds TEXT ) PARTITION BY LIST (ds); CREATE TABLE user_profile_202503 PARTITION OF user_profile FOR VALUES IN ('202503'); CREATE TABLE user_profile_202504 PARTITION OF user_profile FOR VALUES IN ('202504'); COMMIT;
创建逻辑分区表:
保持1个分区键。
CREATE TABLE user_profile_lp_1 ( a TEXT, b TEXT, ds TEXT NOT NULL) LOGICAL PARTITION BY LIST (ds);
改为年和月,保持2个分区键。
CREATE TABLE user_profile_lp_2 ( a TEXT, b TEXT, yy TEXT NOT NULL, mm TEXT NOT NULL) LOGICAL PARTITION BY LIST (yy, mm);
表映射关系
在表属性、分区属性等方面,逻辑分区表与物理分区表的映射关系如下表:
如果原物理分区表分区键使用TEXT等非时间类型,且使用了动态分区管理功能,则转换为逻辑分区表时,暂不支持到期自动清理(参数partition_expiration_time
)、到期自动转冷(参数partition_keep_hot_window
)。
模块 | 功能 | 物理分区表 | 逻辑分区表 |
父表动态分区管理 | 开启动态分区管理功能 | auto_partitioning_enable | 无对应参数,无需关注。 |
时间单位 | auto_partitioning_time_unit | 无需单独配置,但仅支持时间类型分区。 | |
时区 | auto_partitioning_time_zone | 无对应参数,无需关注。 | |
预创建分区数量 | auto_partitioning_num_precreate | 无对应参数,无需关注。 | |
保留历史分区数量 | auto_partitioning_num_retention | 通过partition_expiration_time实现到期自动清理。 | |
保留热分区数量 | auto_partitioning_num_hot | 通过partition_keep_hot_window实现到期自动转冷。 | |
动态分区管理调度时间 | auto_partitioning_schd_start_time | 无对应参数,无需关注。 | |
分区子表日期时间格式 | auto_partitioning_time_format | 无对应参数,无需关注。 | |
子表/子分区管理 | 分区是否保留 | keep_alive | keep_alive |
分区是否保持冷/热存 | storage_mode | storage_mode | |
Binlog | 父表Binlog开关 | binlog_level | binlog_level |
父表Binlog生命周期 | binlog_ttl | binlog_ttl | |
按分区动态管理Binlog | 不支持。 | partition_generate_binlog_window | |
子分区Binlog开关 | 继承父表,不支持修改。 | generate_binlog | |
子分区Binlog生命周期 | 子表支持修改。 | 继承父表,不支持修改。 | |
索引及其他表属性 | 子分区bitmap_columns | 子表支持修改。 | 继承父表,不支持修改。 |
子分区dictionary_encoding_columns | 子表支持修改。 | 继承父表,不支持修改。 | |
orientation、table_group等其他表属性 | 继承父表,不支持修改。 | 继承父表,不支持修改。 | |
primary key、distribution_key、clustering_key等其他索引 | 继承父表,不支持修改。 | 继承父表,不支持修改。 |
存量数据迁移
CLONE
如果您的表结构不需改变,且数据量适中,推荐使用CLONE语法。
该命令会自动创建一张新的逻辑分区表,并将原表数据复制到新表,表结构完全相同。原物理分区表不删除。
如果原表有实时写入任务:
CLONE前,建议手动停止实时写入任务。
CLONE完成后,建议新建实时写入任务,让实时写入的数据源同时写入CLONE前后的两张表,以保证两张表数据一致且完整。
迁移完成后,充分验证新老分区表的数据与功能情况,完成导入任务、查询任务、运维任务适配后,清理原物理分区表。
使用示例:
CALL hg_clone_to_logical_partition('user_profile', 'user_profile_logical');
如果迁移数据较多,运行时间很长,推荐使用ASYNC命令在后台执行。命令提交成功后会返回CALL对应的query_id,可以使用此query_id在Query洞察进一步查看异步任务的执行状况。
SET statement_timeout = 0;
ASYNC CALL hg_clone_to_logical_partition('user_profile', 'user_profile_logical');
手动迁移
如果您的表结构需要改变,或数据量较大、数据迁移压力大,推荐使用手动迁移方式,以便更灵活地控制迁移节奏。
该方式需要手动创建新的逻辑分区表,并将原表数据复制到新表。由于手动建表,因此可灵活优化表属性,灵活控制迁移节奏。
如果原表有实时写入任务:
导入数据前,建议手动停止实时写入任务。
导入数据完成后,建议新建实时写入任务,让实时写入的数据源同时写入导入数据前后的两张表,以保证两张表数据一致且完整。
迁移完成后,充分验证新老分区表的数据与功能情况,完成导入任务、查询任务、运维任务适配后,清理原物理分区表。
迁移步骤:
创建表。
详情请参见本文创建逻辑分区表。
导入历史数据,推荐使用hg_insert_overwrite。
CALL hg_insert_overwrite('logical_partition_table', '{20250601, 20250602}'::text[], 'SELECT * FROM tb');
REBUILD语法(不推荐使用)
若您能够接受较长的变更时间窗口,并且允许部分读写任务出现失败,则可以采用REBUILD语法进行迁移。详情请参见REBUILD(Beta)。
注意事项如下:
使用REBUILD功能迁移分区表,迁移后的逻辑分区表表名不变。原物理分区表表名会改为
tmp_rebuild_old_<query_id>_<unique_id>_<table_name>
。迁移完成后,需要进一步完成剩余事项适配,包括导入任务、查询任务、运维任务适配。
适配工作完成前,相关任务可能由于兼容性产生报错,因此不推荐使用该方式迁移分区表。
使用示例:
-- 为分区字段增加NOT NULL约束
ASYNC REBUILD TABLE user_profile ALTER ds SET NOT NULL;
-- 物理分区表转换为逻辑分区表,并保留原物理分区表
ASYNC REBUILD TABLE user_profile WITH (keep_source) TO logical partition;
导入任务适配
如果原物理分区表的数据导入任务为导入父表(通过Fixed Plan),则无需修改任务。
如果原物理分区表的数据导入任务为导入子表,则需要做如下适配:
删除新建分区子表的语句。逻辑分区表没有物理子表,无需手动创建。
导入任务中的子表表名改为逻辑分区表的父表表名。
场景一:新增子表/子分区并导入数据
-- 原物理分区表导入任务
CREATE TABLE user_profile_202505 PARTITION OF user_profile FOR VALUES IN ('202505');
INSERT INTO user_profile_202505 SELECT a, b, ds FROM <source_table> WHERE ds = '202505';
-- 新逻辑分区表导入任务
INSERT INTO user_profile_lp_1 SELECT a, b, ds FROM <source_table> WHERE ds = '202505';
场景二:回刷子表/子分区数据
如果原物理分区表使用存储过程hg_insert_overwrite
实现子表数据回刷,并且一次回刷多张子表,当迁移为逻辑分区表并使用原生INSERT OVERWRITE语法后,建议按分区拆分任务实现串行。详情请参见INSERT OVERWRITE。
-- 原物理分区表回刷任务(通过创建临时表实现INSERT OVERWRITE)
-- 创建临时表并导入数据
CREATE TABLE tmp_user_profile_202505(a text, b text, ds text);
INSERT INTO tmp_user_profile_202505 SELECT a, b, ds FROM <source_table> WHERE ds = '202505';
-- 临时表RENAME并ATTACH到父表
BEGIN;
DROP TABLE IF EXISTS user_profile_202505;
ALTER TABLE tmp_user_profile_202505 RENAME TO user_profile_202505;
ALTER TABLE user_profile ATTACH PARTITION user_profile_202505 FOR VALUES IN ('202505');
COMMIT;
-- 原物理分区表回刷任务(通过hg_insert_overwrite命令)
CALL hg_insert_overwrite('user_profile' , '202505', $$SELECT a, b, mm FROM <source_table> WHERE ds='202505'$$);
-- 新逻辑分区表回刷任务(通过原生Insert Overwrite语法)
INSERT OVERWRITE user_profile_lp_1 PARTITION (ds = '202505') SELECT a, b, ds FROM <source_table> WHERE ds='202505';
查询任务适配
如果原物理分区表的数据查询任务为查询父表,则无需修改任务。
如果原物理分区表的数据查询任务为查询子表,则需改为查询父表,并增加分区过滤条件。示例如下:
-- 原物理分区表的子表查询任务 SELECT * FROM user_profile_202504; -- 原逻辑分区表的查询任务 SELECT * FROM user_profile_lp_1 WHERE ds = '202504';
运维任务适配
对于原物理分区表与新逻辑分区表的日常运维任务,也可能存在差异。部分场景对比如下:
查询类别 | 物理分区表 | 逻辑分区表 | 说明 |
查询父表DDL | 函数 | 无差异。 | |
查询父表表属性 | 系统表 | 无差异。 | |
查询分区列表 | 系统表 | 有差异。 | |
查询分区属性 | 系统表 | 系统表 | 有差异。 |
查询父表存储 | 系统表 | 系统表 | 有差异。 |