REBUILD(Beta)

Hologres支持通过ALTER TABLE语法对部分表结构、表属性、列属性进行修改,但对于影响表存储的属性,则不支持通过ALTER TABLE语法进行修改。从Hologres V3.1版本起支持REBUILD语法。通过REBUILD语法,您可以灵活修改表的各类参数。本文为您介绍HologresREBUILD的使用方法。

语法

命令格式

ASYNC REBUILD TABLE [ IF EXISTS ] <table_name>
    [ WITH ( <rebuild_parameter> [= <value>] [, ... ] )]  
    <action> [, ... ];
    
WHERE action IS ONE OF:
    ADD [ COLUMN ] <column_name> <data_type> [ column_constraint [ ... ] ]
    ALTER [ COLUMN ] <column_name> [ SET DATA ] TYPE <data_type> [ USING <expression> ]
    ALTER [ COLUMN ] <column_name> SET DEFAULT <expression>
    ALTER [ COLUMN ] <column_name> DROP DEFAULT
    ALTER [ COLUMN ] <column_name> { SET | DROP } NOT NULL
    ALTER PRIMARY KEY (<column_name> [, ...])
    TO [LOGICAL] PARTITION [BY LIST(<column_name> [, <column_name>])]
    SET ( <parameter> [= <value>] [, ... ] )

WHERE rebuild_parameter IS ONE OF:
    keep_source
    binlog_mode
    rebuild_guc_<guc_name> = '<guc_value>'

参数说明

参数

子项

说明

ASYNC

声明该REBUILD任务异步执行,执行后会返回任务的query_id,您可以通过query_id监控任务的执行状态 。暂不支持同步执行。

table_name

需要REBUILD的目标表名。

column_name

目标表的列名。

data_type

列的数据类型。

action

ADD COLUMN

增加列。支持增加非空列并设置默认值。

ALTER COLUMN TYPE

修改列的数据类型。

ALTER COLUMN SET/DROP DEFAULT

为列设置/取消默认值。旧数据的NULL值不会改变。

ALTER COLUMN SET/DROP NOT NULL

为列设置/取消非空约束。

ALTER PRIMARY KEY

修改表的主键。如果新主键存在数据冲突,则会在异步执行过程中报错,请及时关注任务的执行状态。

TO [LOGICAL] PARTITION

转为逻辑/物理分区表,支持如下场景:

  • 普通表转为物理分区表,必须指定分区键。

  • 普通表转为逻辑分区表,必须指定分区键。

  • 物理分区表修改分区键。

  • 物理分区表转为逻辑分区表,可选修改分区键。

  • 暂不支持逻辑分区表转为物理分区表。

SET ( <parameter> [= <value>])

修改表属性,常用场景如下:

  • 修改分布键distribution_key

  • 修改分段键event_time_column

  • 修改聚簇索引clustering_key

  • 修改表存储格式orientation:行存、列存、行列共存转换。

  • 修改表所属的table_group

  • 其他表属性均支持修改。

  • 位图索引bitmap_columns、字典编码列dictionary_encoding_columns无需通过REBUILD修改,直接使用ALTER TABLE语法即可。

WITH (<rebuild_parameter> [= <value>])

设置REBUILD任务相关参数,常用参数包括:

  • keep_source:无需设置value。转换后不删除原表,原表会改名为tmp_rebuild_old_<query_id>_<unique_id>_<table_name>

  • binlog_mode : 无需设置value。可以对开启Binlog的表执行Rebuild,需参考下文的使用示例进行操作,以免丢失Binlog数据。

  • rebuild_guc_hg_computing_resource='serverless':使用Serverless资源执行本次REBUILD任务,无需占用本实例资源,任务更加稳定。

  • rebuild_guc_<guc_name>='<guc_value>':其他GUC参数均可在此设置,详情请参见GUC参数

注意事项

  • 仅支持异步ASYNC,无需长时间占用连接。

  • REBUILD任务提交后会很快执行成功,并返回任务的query_id。您可基于此query_id进一步查看REBUILD任务执行状态。如果提交任务后一直未成功,可能是由于当前实例下的异步调度任务较多,建议等待一段时间,待返回query_id后查看任务执行状态。

  • 使用REBUILD功能修改表参数涉及底层数据重分布,需要消耗计算资源。因此,建议您在业务低峰期对表执行REBUILD任务,或采用Serverless Computing资源进行此操作,以确保业务的稳定性。

  • REBUILD任务执行期间,其中一个步骤会将该表设为只读,在此阶段时间内表无法进行写入操作。

  • 如果需要修改多个参数,推荐在同一个REBUILD任务中一次性完成,以降低开销。

使用示例

对未开启Binlog的表执行REBUILD

-- 创建表并导入数据
CREATE TABLE rebuild_test (
    a TEXT,
    b TEXT,
    ds TEXT
);

INSERT INTO rebuild_test VALUES ('1', '1', '2025-04-01'), ('2', '2', '2025-04-02'), ('3', '3', '2025-04-03');

-- 新增非空列并设置默认值
ASYNC REBUILD TABLE rebuild_test ADD COLUMN c text NOT NULL DEFAULT 'a';

-- 将主键改为a列
ASYNC REBUILD TABLE rebuild_test ALTER PRIMARY KEY (a);

-- 使用Serverless资源执行Rebuild任务,为表设置distribution_key和clustering_key,并改为行列共存
ASYNC REBUILD TABLE rebuild_test 
WITH (
    rebuild_guc_hg_computing_resource = 'serverless'
)
SET (
    distribution_key = 'a',
    clustering_key = 'a',
    orientation = 'row,column'
);

-- 将非分区表转为逻辑分区表,分区键设为ds(同时为ds列增加NOT NULL属性)
ASYNC REBUILD TABLE rebuild_test 
    ALTER COLUMN ds SET NOT NULL,
    TO LOGICAL PARTITION BY LIST(ds);

对开启Binlog的表执行REBUILD

REBUILD不支持保留表的历史Binlog数据,因此常规模式下,不支持对开启了Binlog的表执行REBUILD。您需在REBUILD任务中配置binlog_mode参数,并按下文步骤执行REBUILD,以保证历史Binlog数据已被下游100%消费完成。

  1. 执行REBUILD。

    ASYNC REBUILD TABLE rebuild_test 
    WITH (
      binlog_mode
    )
    <your_action>;
  2. 对已设置binlog_mode参数的REBUILD任务,且在set_readonly步骤执行完成后,任务会自动暂停,可以通过如下SQL查询进度。此时系统已将该表设为只读,该表无法写入数据,也即没有新的Binlog数据生成。

    postgres=# SELECT step, status, progress FROM hologres.rebuild_progress('<query_id>');
                 step              | status | progress 
    -------------------------------+--------+----------
     prepare                       | done   | 1/1
     create_tmp_table              | done   | 1/1
     get_src_table_snapshot        | done   | 1/1
     insert                        | done   | 1/1
     set_readonly                  | done   | 1/1
     check_snapshot                |        | 0/1
     re-insert                     |        | -
     check_additional_child_table  |        | -
     create_additional_child_table |        | -
     insert_additional_child_table |        | -
     swap                          |        | 0/1
    (11 rows)
  3. 等待下游客户端将存量Binlog消费完成,然后手动执行如下SQL继续执行REBUILD任务。任务继续执行期间,原表仍保持只读,不产生新的Binlog数据。

    RESUME '<query_id>';

    REBUILD任务成功执行后,新表会自动开启Binlog,此时可以重启下游Binlog消费任务,从lsn = 0开始消费新表的Binlog。

监控与运维

查看REBUILD任务执行状态

REBUILD任务以异步方式执行,只要任务提交成功,任务本身便会返回成功状态和query_id。您需要通过系统表hologres.rebuild_progress查看异步执行的子任务状态,全部成功才表示该表REBUILD完成。命令如下:

SELECT * FROM hologres.rebuild_progress('<rebuild_query_id>');

系统表的列以及相关说明如下:

列名称

说明

job_name

REBUILD任务的query_id。

step_id

步骤ID。REBUILD的子任务按照此ID顺序依次执行。

step

步骤名:

  • prepare:任务准备。

  • create_tmp_table:创建临时表。

  • get_src_table_snapshot:获取原表的数据快照。

  • insert:存量数据导入到临时表。

  • set_readonly:将待REBUILD的表设为只读,数据停写。

  • check_snapshot:检查此时表的数据快照是否与第三步获取的相同,如果不同则进入re-insert步骤。

  • re-insert:增量数据导入。

  • check_additional_child_table:检查从开始REBUILD到现在是否有新的子表被用户创建,仅针对物理分区表。

  • create_additional_child_table:为临时表创建潜在的新子表,仅针对物理分区表。

  • insert_additional_child_table:存量数据导入到新临时子表,仅针对物理分区表。

  • swap:临时表替代原表。

status

子任务状态。

  • done:已完成。

  • doing:正在执行。

  • NULL:无需执行该步骤,或目前无法得知是否需要执行该步骤。

  • error:执行失败。需检查message字段中的报错信息。

progress

子任务进度:m/n。n为需要执行的substep个数(一般和分区个数正相关),m为当前已执行的substep个数。

start_time

子任务的开始时间。

end_time

子任务的结束时间。

queryid

子任务的query_id。

pid

服务进程id。

message

子任务的message。如果子任务报错,则报错信息记录在该字段中。

结果示例如下:

opopo

停止与重启REBUILD任务

  • 停止REBUILD异步任务。

    SUSPEND '<query_id>';
  • 继续执行CANCEL掉的异步任务。

    RESUME '<query_id>';

REBUILD任务异常处理

如果REBUILD任务执行过程中发生报错导致任务中断,或您手动执行SUSPEND命令暂停了REBUILD任务,您可以通过RESUME命令继续执行该REBUILD任务,也可以通过如下步骤结束REBUILD任务以恢复原表。

  • 通过如下命令清理REBUILD过程中产生的临时表。

    CALL hg_clean_rebuild_tmp_tables('<query_id>');
  • 如果原表被REBUILD任务置为只读状态后任务中断,则需通过如下命令取消原表的只读状态,恢复写入。

    ALTER TABLE <table_name> SET (readonly = false);