表建好之后想加分区,过去只能重建:新建一张分区表,双写、回补历史数据、再切流量。GreptimeDB v1.1 支持对已有的未分区表直接执行
ALTER TABLE加分区,不需要重建。
分区通常在建表时就定死了
大多数支持分区的数据库,分区规则要在建表时确定,之后很难修改。数据量小的时候,一张表一个分片就够用,看不出影响;数据规模变大以后,问题才会暴露出来。
以一张 sensor_readings 表为例,建表时没有分区。随着设备从几十台增加到几千台,写入从每秒几千行增加到 5 万行,全部落在同一个 Region、同一个节点上。这个节点会成为瓶颈:写入延迟升高,查询变慢,CPU 和磁盘接近满载,而集群里其他节点仍然空闲。
这时想给表加分区、把负载分散到多个节点,但分区规则已经无法修改。传统做法只有一条路径:
- 按新的分区规则建一张新表;
- 业务侧改成双写,新老表同时写;
- 把历史数据从老表回补到新表;
- 校验一致性,切读流量,最后下线老表。
TB 级历史数据的迁移耗时很长,占用带宽、影响线上业务,还需要业务方改代码配合。因此分区方案往往要在建表时就规划好,后期调整的成本很高。
GreptimeDB v1.1 解决的就是这个问题:对一张已存在的、未分区的表,在线加上分区。
v1.1:一条 DDL 完成在线加分区
执行下面的语句:
ALTER TABLE sensor_readings PARTITION ON COLUMNS (device_id, area) (
device_id < 100 AND area < 'South',
device_id < 100 AND area >= 'South',
device_id >= 100 AND area <= 'East',
device_id >= 100 AND area > 'East'
);执行后,原本集中在单个 Region 的 sensor_readings 会拆成 4 个分区,分别调度到 4 个节点,负载分散,写入吞吐随节点数增加。过程中不需要新建表、双写或回补历史数据,业务代码也不需要改动。

ALTER TABLE 拆成多节点,再到用 SPLIT / MERGE 持续调优。实现原理:存算分离
这项能力依赖的不是 SQL 语法,而是底层架构,也就是存算分离的设计。
传统 shared-nothing 架构中,每个节点的数据存放在本地磁盘上。重新分区需要在节点之间物理迁移数据,把 TB 级文件从一台机器复制到另一台。这个过程慢、占用资源,也是很多系统不支持建表后修改分区的原因。
GreptimeDB 的数据存放在共享对象存储上(S3 及兼容存储),不绑定到任何单个节点的本地磁盘。Region 是逻辑分片,通过 manifest 文件引用对象存储上的数据,本身不持有数据。因此重分区是一次元数据操作:更新每个 Region 的 manifest 文件引用、切换到新的分区布局、重新计算路由,数据不需要在节点之间迁移。

存算分离让计算和存储各自独立伸缩,分区布局可以随负载调整,不必在建表时固定。同样是给大表重新分区,本地磁盘架构下是一次数据迁移工程,在 GreptimeDB 上是一次在线的元数据切换。
重分区期间写入可能会有短暂波动,官方建议客户端开启重试,即可平稳过渡。
分区之后:拆分与合并
把未分区表变成分区表只是第一步。数据分布会随时间变化,当前均衡的分区之后可能出现热点或冷区。GreptimeDB 提供两个操作调整已有分区:SPLIT PARTITION 拆分过热的分区,提升写入并发;MERGE PARTITION 合并变冷、变小的分区,回收资源。
-- 拆分热点分区
ALTER TABLE sensor_readings SPLIT PARTITION (
device_id < 100 AND area < 'South'
) INTO (
device_id < 50 AND area < 'South',
device_id >= 50 AND device_id < 100 AND area < 'South'
);
-- 合并冷分区
ALTER TABLE sensor_readings MERGE PARTITION (
device_id >= 100 AND area <= 'East',
device_id >= 100 AND area > 'East'
);除了在现有分区列上拆分,SPLIT PARTITION ... ON COLUMNS 还能在拆分的同时引入新的分区列。比如一张表最初只按 device_id 分区,后来想再按 area 细分:
-- 初始只按 device_id 分区
ALTER TABLE sensor_readings PARTITION ON COLUMNS (device_id) (
device_id < 100,
device_id >= 100
);
-- 拆分时引入新的分区列 area
ALTER TABLE sensor_readings SPLIT PARTITION (
device_id < 100
) ON COLUMNS (device_id, area) INTO (
device_id < 100 AND area < 'South',
device_id < 100 AND area >= 'South'
);拆分完成后,表的分区列会更新为 (device_id, area)。这样分区维度本身也能随业务演进,而不只是在既有维度上调整边界。
已分区表的拆分与合并有完整的分步示例,可参考另一篇教程:如何在 GreptimeDB 中在线拆分与合并分区。
配合 PARTITION ON COLUMNS 的首次分区能力,就形成了完整的流程:从未分区,到分区,再到随负载调整。
运维闭环:诊断、执行、迭代
在线重分区让容量运维成为一个可观测、可迭代的过程。
诊断阶段先确认哪个 Region 负载偏高。把 Region 级统计和分区规则关联查询:
SELECT
t.table_name,
r.region_id,
r.region_number,
p.partition_name,
p.partition_description,
r.written_bytes_since_open,
r.region_rows
FROM information_schema.region_statistics r
JOIN information_schema.tables t
ON r.table_id = t.table_id
JOIN information_schema.partitions p
ON p.table_schema = t.table_schema
AND p.table_name = t.table_name
AND p.greptime_partition_id = r.region_id
WHERE t.table_schema = 'public'
AND t.table_name = 'sensor_readings'
ORDER BY r.written_bytes_since_open DESC
LIMIT 10;written_bytes_since_open 长期偏高的分区是优先拆分的对象。同时查询 information_schema.region_peers 确认对应节点健康,避免把节点抖动误判为热点。
除了 SQL,GreptimeDB 内置的 Grafana Dashboard 也加入了 Hotspot 面板(Hotspot Regions、Datanode 写入负载与数据分布),可以直接从图表上定位热点 Region 和写入倾斜的 Datanode,参见 greptimedb#8098。
执行阶段在线运行对应的 ALTER TABLE,更新元数据,其间写入可能有短暂波动。
迭代阶段观察新的负载分布,按需继续拆分或合并。
注意事项
在线重分区依赖存算分离架构,因此有几个前置条件:
- 只支持分布式集群,单机版无法重分区。
- 必须使用共享对象存储(如 AWS S3),保证所有 Datanode 都能访问同一份数据。
- Metasrv 和所有 Datanode 都要开启 GC。对象存储保存 Region 文件,GC 负责在旧引用释放之后再回收文件,避免重分区过程中误删仍在使用的数据。
还有几个实操细节:
SPLIT/MERGE的分区参数要精确匹配一条现有的分区规则。常见的是 1 拆 2、2 合 1,更复杂的变更可以分几步拆分和合并完成。- 重分区语句支持异步执行。加上
WITH (WAIT = false)会立即返回一个procedure_id,用ADMIN procedure_state(procedure_id)查进度;TIMEOUT控制整体时限,无论WAIT是 true 还是 false 都会生效。
ALTER TABLE sensor_readings SPLIT PARTITION (
device_id < 100 AND area < 'South'
) INTO (
device_id < 50 AND area < 'South',
device_id >= 50 AND device_id < 100 AND area < 'South'
) WITH (
TIMEOUT = '5m',
WAIT = false
);对评估者的意义
如果你正在评估 GreptimeDB 的扩展能力和运维成本,在线重分区改变了两件事。
一是扩展性。表的容量不再受限于建表时的分区决策,线上表可以随数据增长重新分区、横向扩展,不用停机重建。
二是运维成本。得益于存算分离,重分区是一次轻量的元数据切换,而不是一次 TB 级的数据迁移。分区规划不必在建表时一次定死,可以随负载持续调整。
企业版:用 Autopilot 自动均衡负载
前面介绍的都是手动重分区:自己诊断热点、决定拆分或合并、再执行。GreptimeDB 企业版的 Autopilot 把这套流程自动化。它运行在 Metasrv 中,持续采集 Datanode 和 Region 的写入统计,并对短期波动做平滑,在满足配置条件时自动提交调度动作。
Autopilot 包含两个互补的策略:
- Auto Repartition:自动把可能成为瓶颈的大 Region 拆成更小的 Region。它作用在已经有分区规则的表上——也就是说,先用
PARTITION ON COLUMNS给表建立分区,之后的持续拆分就可以交给它自动完成;对完全没有分区规则的表,它不会自动生成分区。 - Region Balancer:自动把热 Region 在 Datanode 之间迁移,均衡各节点的写入负载。
两者共用同一套运行时和集群统计,配合起来就能让分区分布和节点负载持续保持均匀,把手动诊断和决策的成本省下来。相关行为可以通过 plugins.auto_repartition、plugins.region_balancer 等配置项调整,比如拆分触发比例、单次最多拆几份、冷却时间等。
延伸阅读
- 如何在 GreptimeDB 中在线拆分与合并分区——已分区表的拆分与合并分步教程
- 重分区文档——前置条件、热点识别与完整语法
- ALTER TABLE 参考——重分区的 SQL 语法细节
- Autopilot 文档——企业版 Auto Repartition 与 Region Balancer


