痛点:建表容易,改表难
在 Hologres 里,Table Group(TG)决定了一张表的 shard 数。shard 数直接影响查询和写入性能------过少会限制并行度形成瓶颈,过多则带来额外调度与资源开销。合理的 shard 数很大程度上取决于数据量,但实践中存在一个根本性难题:很多业务在建表时根本无法准确预估未来的数据量。
以游戏业务为例,无法提前判断哪款游戏会在什么时候成为爆款,数据规模可能在短期内出现数量级增长。这就导致建表时的 shard 数选择往往与后续实际需求严重错配。过去想要扩 shard,通常需要通过 rebuild 方式完成------新建目标分布,再把原表数据重新导入。对大表来说这条路耗时随数据量线性增长,期间消耗大量 IO、CPU 和存储资源,也会拉长业务调整窗口。
Hologres 4.2 版本推出的 Liquid Table 正是要解决这个痛点:让表的 shard 数成为可以随时流动调整的配置,而非建表时一锤定音的静态决策。

一行 SQL,秒级 Reshard
sql
-- 创建目标 Table Group,决定新的 shard 数
CALL hg_create_table_group('tg_128', 128);
-- 一行 ALTER 完成在线扩容
ALTER TABLE public.orders SET (table_group = 'tg_128');
-- 可选:配置后台数据重组织窗口
ALTER TABLE public.orders SET (
liquid_table_enable_data_reorganization = true,
liquid_table_reorganization_partition_window = '3 day'
);
ALTER 命令秒级返回,新写入和新查询立即使用新的 shard 分布。无需重建表、无需停服、无需手工迁移数据。
秒级生效的核心原理

传统 rebuild 之所以慢,根本原因是把"修改分布"和"搬迁历史数据"绑定成了一个原子操作。Liquid Table 的核心思路是将这两件事解耦:
元数据先切换,数据文件不动。 Reshard 时系统不会同步重写历史文件,而是先完成 TG 和 shard 布局的元数据切换,让新写入立即进入新的分布。
后台逐步重组织。 Reshard 生效后,后台按用户配置逐步将旧布局文件重排为新布局文件,不阻塞业务。
因此,用户感知到的 reshard 生效时间主要取决于元数据切换(秒级),而非表的数据量。
Over-sharding:让读放大在过渡期也可控
元数据先行切换意味着历史文件暂时保持旧的物理形态,这就会导致,旧文件的数据范围可能会横跨多个新 shard区间,查询时多个shard需要重复扫描同一个文件,读取额外数据再过滤属于本shard的行------这就是读放大。
Liquid Table 通过 over-sharding 机制提前应对:在日常 compaction 中,输出文件时不仅按当前 shard 边界切分,还在每个 shard 内部进一步切成更细的子范围。假设当前 64 shard、over-sharding factor 为 2,则每个 shard 内部文件被切为 2 段,物理粒度等效于 128 个逻辑分片。

当从 64 扩到 128 shard 时:在没有 over-sharding 的情况下,每个旧文件会横跨两个新 shard,每个 shard 都需要重复读取该文件,造成 2 倍的读放大。有 over-sharding(factor=2)的情况下,一个旧文件在 reshard 后依旧只属于一个 shard,没有读放大。
这个机制嵌入在日常 compaction 中自动生效------即使当下没有 reshard 计划,数据已经提前准备好了更细的粒度。
后台 Reorganization:热数据优先,冷数据可延后

Liquid Table 不要求所有历史数据立刻完成物理重排。用户可以根据业务特征选择策略:
只重排热数据------对时间分区表设置liquid_table_reorganization_partition_window = '3 day',只对窗口内的近期分区进行重排,窗口外的冷数据不做任何处理。
重排全量数据------使用较大的时间窗口或默认全量重排,适合对全表查询延迟都有要求的场景。
先切换,后重排------Reshard 秒级生效让业务逻辑先跑起来,后台再利用空闲资源逐步完成数据布局优化。由于 over-sharding 已经预先控制了读放大,过渡期内查询性能通常不会有明显退化。
这种模式尤其适合大表、热点窗口明显、或不希望一次性打满后台资源的场景。
性能实测
查询性能:TPC-H 500G cold run
在未开启 data reorganization 的条件下(每次运行前清理 cache),以初始 32 shard 的表为基准,依次 reshard 到不同 shard 数,TPC-H 查询耗时如下:
|---------|--------|
| Shard 数 | 耗时 |
| 32(原始) | 196.1s |
| 64 | 185.2s |
| 128 | 185.9s |
| 256 | 188.6s |
Reshard 后查询性能没有回退,不同 shard 数之间的耗时差异仅来自 shard 数本身对并行度的影响,而非 reshard 引入的额外开销。
注:
Hologres 默认在数据量较小的表上不启用 over-sharding 优化。TPC-H 包含一些数据量较小的表,因此本次测试中强制启用了 over-sharding,使得所有表都开启over-sharding 优化。
只有当 shard 数为 2 的幂时,典型的整倍扩缩容(如 32→64→128)才能让 over-sharding 完全避免读放大带来的性能下降;如果 shard 数非 2 的幂,reshard 后仍可能存在小幅的性能回退。
Reshard 耗时
Reshard 耗时与表的文件数呈正相关,在一个较大规模的测试场景中:总数据量 10TB、20 万文件的表、从 80 shard 扩到 160 shard,reshard 操作耗时仅 1.5 秒。
|-----|------|-----------|
| 文件数 | 数据量 | Reshard耗时 |
| 20万 | 10TB | 1.5秒 |
兼容性
Liquid Table 支持列存、行存、行列共存三种存储格式,并与 Hologres 大部分核心功能正交兼容:Dynamic Table、全局二级索引(GSI)、全文倒排索引、向量索引(HGraph)、逻辑分区表、Time Travel、Binlog 等均已支持。暂不物理分区表。
Shard 规划建议
-
Shard 数建议设置为 2 的幂(如 32、64、128、256),这样在典型的整倍扩缩容时,一般不会受到读放大带来的性能损失。
-
Shard数一般和数据量呈正相关,可参考推荐配置:help.aliyun.com/zh/hologres... Shard数过多或者过少都可能会对性能造成负面影响。
建表示例
sql
-- 列存 Liquid Table(OLAP 场景)
CREATE TABLE user_events (
user_id BIGINT NOT NULL,
event_ts TIMESTAMPTZ NOT NULL,
event TEXT,
payload JSONB,
PRIMARY KEY(user_id, event_ts)
) WITH (liquid_table = 'true');
-- 将普通表转为 Liquid Table
ASYNC REBUILD TABLE normal_table
SET (
liquid_table = 'true'
);
未来展望
Reshard 只是 Liquid Table 的第一步。在传统数据库中,表的分布属性------shard 数、distribution key、clustering key------一旦建表确定就如同固化的冰块。Liquid Table 的愿景是让这些属性变成可以流动的液体,这也是"Liquid"这个名字的由来。
后续我们计划将"秒级切换 + 后台渐进重排"的机制扩展到 clustering key 等更多分布属性上,让任何一次建表时的选择都不再是不可逆的。
此外,为了便于普通表转换为liquid table,我们还将在未来发布普通表无需Rebuild,一键立即转换为liquid table的能力,可大幅节约转换开销,对读写无影响。