REBUILD modifies a table's schema, storage properties, or partitioning in the background without taking the table offline. Unlike ALTER TABLE, which is limited to metadata changes, REBUILD rewrites table data in the background and atomically swaps in the new table when it's ready.
REBUILD is available in Hologres V3.1 and later. Unlike a standard DDL statement, REBUILD always runs asynchronously — the command returns a query_id immediately, and the actual data rewriting happens as a background task. The table enters a brief read-only window near the end of the process, but remains available for reads throughout.
How it works
Submitting a REBUILD command triggers a sequence of background steps:
prepare — allocates task resources.
create_tmp_table — creates a temporary table with the new schema.
get_src_table_snapshot — takes a snapshot of the source table data.
insert — copies the snapshot into the temporary table.
set_readonly — sets the source table to read-only and stops writes.
check_snapshot — checks whether new data arrived after the snapshot; if so, triggers re-insert.
re-insert — copies incremental data (runs only if the snapshot changed).
check_additional_child_table, create_additional_child_table, insert_additional_child_table — handle any new child partitions added during the task (physical partitioned tables only).
swap — atomically replaces the source table with the temporary table.
The table is read-only during steps 5–9, so write downtime is minimized. The swap step is atomic: readers see either the old table or the new table, never a mixed state. Starting from Hologres V4.1, Dynamic Table technology further reduces the read-only window when specific conditions are met.
Syntax
ASYNC REBUILD TABLE [ IF EXISTS ] <table_name>
[ WITH ( <rebuild_parameter> [= <value>] [, ... ] ) ]
<action> [, ... ];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>] [, ... ] )rebuild_parameter is one of:
keep_source
binlog_mode
rebuild_guc_<guc_name> = '<guc_value>'Parameters
Actions
| Action | Description |
|---|---|
ADD COLUMN | Adds a column. Supports NOT NULL columns with a default value. |
ALTER COLUMN TYPE | Changes the data type of a column. |
ALTER COLUMN SET DEFAULT | Sets a default value for a column. Existing NULL values are not changed. |
ALTER COLUMN DROP DEFAULT | Removes the default value from a column. |
ALTER COLUMN SET/DROP NOT NULL | Adds or removes the NOT NULL constraint on a column. |
ALTER PRIMARY KEY | Changes the primary key. If the new primary key causes a data conflict, the task fails during async execution — monitor the task status. |
TO [LOGICAL] PARTITION | Converts the table to a partitioned table. See Supported partition conversions. |
SET | Modifies table properties such as distribution_key, event_time_column, clustering_key, orientation, and table_group. |
To modifybitmap_columnsordictionary_encoding_columns, use ALTER TABLE instead of REBUILD.
WITH parameters
| Parameter | Description |
|---|---|
keep_source | Keeps the source table after the rebuild instead of deleting it. The source table is renamed to tmp_rebuild_old_<query_id>_<unique_id>_<table_name>. |
binlog_mode | Allows REBUILD on a table with binary logging enabled. See Rebuild a table with binary logging enabled. |
rebuild_guc_hg_computing_resource='serverless' | Runs the REBUILD task using Serverless computing resources, preventing it from consuming your instance's resources and improving stability. |
rebuild_guc_<guc_name>='<guc_value>' | Sets additional GUC parameters. For available parameters, see GUC parameters. |
Supported partition conversions
| From | To | Notes |
|---|---|---|
| Standard table | Physical partitioned table | Partition key required. |
| Standard table | Logical partitioned table | Partition key required. |
| Physical partitioned table | Physical partitioned table | Change the partition key. |
| Physical partitioned table | Logical partitioned table | Partition key change is optional. |
| Logical partitioned table | Physical partitioned table | Not supported. |
Usage notes
Performance and scheduling
REBUILD rewrites table data and consumes significant computing resources. Run REBUILD tasks during off-peak hours, or use
rebuild_guc_hg_computing_resource='serverless'to keep instance resources available for production workloads.Combine multiple changes into a single REBUILD task to reduce overhead.
After submitting a REBUILD task, the submission completes quickly and returns a
query_id. If the submission takes longer than expected, the instance may have many asynchronous scheduling tasks running. Wait for thequery_idto be returned before checking the task execution status.
Write availability
The table is read-only during part of the rebuild (steps
set_readonlythroughswap). No writes are accepted during this period.Starting from V4.1, Dynamic Table technology significantly reduces the read-only window. All of the following conditions must be met:
V4.1 conditions for reduced read-only duration
The table has a primary key before the rebuild, and the new primary key includes all columns of the original primary key.
The table uses column store or row-column hybrid store before the rebuild.
The table has no generated columns after the rebuild.
If the table is a physical partitioned table before the rebuild, the partition key must remain unchanged.
If the table becomes a logical partitioned table after the rebuild, it can have only one partition key.
Physical partitioned tables
After rebuilding a physical partitioned table, the following properties are not carried over to the new table. Set them again after the task completes:
The
auto_partitioningproperty on the parent table.Per-child-table properties such as
keep_alive.Properties independently set on individual child tables (such as
bitmap_columnsanddictionary_encoding_columns) revert to the parent table's values.
Limitations
REBUILD is not supported for tables that have:
Column-store optimization on JSONB columns, or vector field column constraints.
Full-text indexes or global secondary indexes.
Columns of the
SerialorBigserialtype.Dynamic Table or materialized view dependencies. (Standard view dependencies are supported.)
Examples
Rebuild a table without binary logging enabled
-- Create a table and insert data
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');
-- Add a NOT NULL column with a default value
ASYNC REBUILD TABLE rebuild_test ADD COLUMN c text NOT NULL DEFAULT 'a';
-- Change the primary key to column a
ASYNC REBUILD TABLE rebuild_test ALTER PRIMARY KEY (a);
-- Use Serverless resources, set distribution_key and clustering_key, and switch to row-column hybrid store
ASYNC REBUILD TABLE rebuild_test
WITH (
rebuild_guc_hg_computing_resource = 'serverless'
)
SET (
distribution_key = 'a',
clustering_key = 'a',
orientation = 'row,column'
);
-- Convert the table to a logical partitioned table with ds as the partition key
ASYNC REBUILD TABLE rebuild_test
ALTER COLUMN ds SET NOT NULL,
TO LOGICAL PARTITION BY LIST(ds);Rebuild a table with binary logging enabled
REBUILD does not preserve historical binary logging data. By default, running REBUILD on a table with binary logging enabled is blocked. Use the binlog_mode parameter and follow this procedure to make sure downstream consumers finish processing existing data before the table is swapped.
Run REBUILD with
binlog_mode:ASYNC REBUILD TABLE rebuild_test WITH ( binlog_mode ) <YOUR_ACTION>;The task pauses automatically after the
set_readonlystep. At this point, the table is read-only — no new binary logging data is generated. Query the progress to confirm:SELECT step, status, progress FROM hologres.rebuild_progress('<query_id>');Expected output:
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)Wait for all downstream consumers to finish processing the existing binary log data. Then resume the task:
RESUME '<query_id>';
After the rebuild completes, binary logging is automatically enabled on the new table. Restart downstream consumers and begin consuming from lsn = 0.
Monitor and manage REBUILD tasks
View task progress
Query the hologres.rebuild_progress system table to check the status of a running or completed REBUILD task:
SELECT * FROM hologres.rebuild_progress('<rebuild_query_id>');The table is fully rebuilt only after all subtasks show done. The following table describes the system table columns:
| Column | Description |
|---|---|
job_name | The query_id of the REBUILD task. |
step_id | The step sequence number. Steps run in order based on this ID. |
step | The step name. See How it works for a description of each step. |
status | The step status: done (completed), doing (in progress), NULL (not needed or not yet determined), or error (failed — check the message column). |
progress | The substep progress as m/n, where n is the total number of substeps (proportional to the number of partitions) and m is the number completed. |
start_time | When the step started. |
end_time | When the step ended. |
queryid | The query_id of the subtask. |
pid | The service process ID. |
message | The step message. Contains the error message if the step failed. |
The following screenshot shows an example of the query result:

Stop and resume a task
-- Pause a running REBUILD task
SUSPEND '<query_id>';
-- Resume a paused or interrupted REBUILD task
RESUME '<query_id>';Handle task failures
If a REBUILD task fails or is paused with SUSPEND, resume it with RESUME, or clean up and restore the table manually:
Clean up temporary tables created during the REBUILD:
CALL hg_clean_rebuild_tmp_tables('<query_id>');If the source table was set to read-only before the task was interrupted, restore write access:
ALTER TABLE <table_name> SET (readonly = false);