物理分区表迁移为逻辑分区表

Hologres V3.1版本支持逻辑分区表。相比于物理分区表,逻辑分区表可有效解决表数量过多、元数据膨胀而可能产生的稳定性问题。本文为您介绍如何将物理分区表迁移为逻辑分区表。

使用场景

针对如下场景建议您由物理分区表迁移为逻辑分区表:

  • Table Group下的物理分区表的子分区表数量多(例如大于10000张),元数据规模大。

  • 每日新增分区数量多,DDL操作次数多。

迁移方案

方案一:先双写验证再迁移业务

使用该方案进行分区表迁移,能够最大程度降低对业务的影响,保证业务稳定性。流程如下:

  1. 停止原物理分区表数据导入任务,新建逻辑分区表,并完成存量数据迁移。存量数据迁移方案,详情请参见存量数据迁移

    • 如果表结构不需改变,且数据量适中,推荐使用CLONE语法。

    • 如果表结构需要改变,或数据量较大、数据迁移压力大,推荐使用手动迁移方式。

  2. 对新逻辑分区表创建数据导入任务,同时启动新老分区表的数据导入任务(即双写)。

  3. 新逻辑分区表业务验证。

  4. 业务迁移,通过如下两个方式。

    • (推荐)将查询直接迁移到新逻辑分区表上,即修改查询任务的目标表名为新逻辑分区表名,同时按需增加分区过滤条件。

    • 将新逻辑分区表RENAME为原物理分区表名,并修改对原物理分区子表的写入与查询任务,改为写入与查询父表并增加分区过滤条件。命令如下:

      BEGIN;
      ALTER TABLE <source_table_name> RENAME TO <source_table_name_archive>;
      ALTER TABLE <target_table_name> RENAME TO <source_table_name>;
      COMMIT;
  5. 运维任务适配。

(不推荐)方案二:快速迁移

若您能够接受较长的变更时间窗口,并且允许部分读写任务出现失败,则可以采用REBUILD语法进行迁移。流程如下:

  1. 停止原物理分区表数据导入任务。

  2. 使用Rebuild语法完成存量数据迁移。详情请参见REBUILD语法

  3. 修改导入任务,并启动导入任务。

  4. 查询任务适配。

  5. 运维任务适配。

分区表迁移

表结构转换

逻辑分区表与原物理分区表相比,在建表语句方面,涉及如下转换工作。

  • 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_idQuery洞察进一步查看异步任务的执行状况。

SET statement_timeout = 0;
ASYNC CALL hg_clone_to_logical_partition('user_profile', 'user_profile_logical');

手动迁移

如果您的表结构需要改变,或数据量较大、数据迁移压力大,推荐使用手动迁移方式,以便更灵活地控制迁移节奏。

说明
  • 该方式需要手动创建新的逻辑分区表,并将原表数据复制到新表。由于手动建表,因此可灵活优化表属性,灵活控制迁移节奏。

  • 如果原表有实时写入任务:

    • 导入数据前,建议手动停止实时写入任务。

    • 导入数据完成后,建议新建实时写入任务,让实时写入的数据源同时写入导入数据前后的两张表,以保证两张表数据一致且完整。

  • 迁移完成后,充分验证新老分区表的数据与功能情况,完成导入任务、查询任务、运维任务适配后,清理原物理分区表。

迁移步骤:

  1. 创建表。

    详情请参见本文创建逻辑分区表

  2. 导入历史数据,推荐使用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

函数hg_dump_script

无差异。

查询父表表属性

系统表hologres.hg_table_properties

无差异。

查询分区列表

查询所有分区子表

系统表hologres.hg_list_logical_partition

有差异。

查询分区属性

系统表hologres.hg_table_properties

系统表hologres.hg_logical_partitioned_table_properties

有差异。

查询父表存储

系统表hg_table_storage_status

系统表hologres.hg_partition_storage_status

有差异。