模式与分区演进是什么
Iceberg 允许在不重写历史数据的前提下改表结构:新增列、向兼容方向扩宽类型、重命名列、删除列,以及调整分区字段。能这样做是因为元数据用字段 ID 而不是列名关联数据,重命名只是改元数据;分区字段变化也只影响之后写入的文件,历史文件按各自记录的分区布局读取。约束也很明确:类型只能往更宽的方向变,删列之后元数据里不再有该字段,重新加同名列不会自动接回原数据。
基本信息
| 新增列 | ALTER TABLE ... ADD COLUMN,老数据该列为空 |
|---|---|
| 类型变更 | 仅支持兼容方向,如 int 到 long、decimal 精度提升 |
| 重命名 | 元数据操作,靠字段 ID 关联,不重写数据 |
| 删除列 | 元数据操作,删除后该字段在元数据中消失 |
| 分区演进 | ADD 或 DROP PARTITION FIELD,只影响新写入的数据 |
| 历史数据读取 | 按文件自身记录的分区布局读取,不受新布局影响 |
| 影响面 | 结构变更会影响所有下游 SQL,上线前需要广播 |
典型使用场景
- 上游新增业务字段:ADD COLUMN 后下游按需读取,老分区该列为空
- 字段改名统一命名规范:元数据操作即可完成,不需要重灌历史数据
- 分区粒度调整:从按月分区改成按天分区,新数据按新布局写入,历史数据照常可读
- 金额精度扩宽:decimal 精度提升属于兼容变更,历史数据无需重写
- 清理无用列:确认没有下游引用后删除,减少表结构复杂度
演进操作示例
演进操作示例
-- 新增列,历史数据该列为空
ALTER TABLE demo.db.trade_order ADD COLUMN channel STRING COMMENT '渠道';
-- 类型向兼容方向扩宽:int 到 long、decimal 精度提升都安全
ALTER TABLE demo.db.trade_order ALTER COLUMN pay_amt TYPE DECIMAL(20,4);
-- 字段改名是元数据操作,历史数据不重写
ALTER TABLE demo.db.trade_order RENAME COLUMN channel TO sale_channel;
-- 分区演进:新数据按新布局写入,历史文件仍按原布局读取
ALTER TABLE demo.db.trade_order ADD PARTITION FIELD days(dt);
-- 核对当前结构
DESCRIBE demo.db.trade_order;演进操作逐项读法
| 操作 | 是否重写数据 | 限制 | 影响面 |
|---|---|---|---|
| 新增列 | 否 | 老数据默认空值 | 下游需处理空值 |
| 类型扩宽 | 否 | 仅兼容方向 | 读取侧类型需同步 |
| 字段改名 | 否 | 纯元数据操作 | 引用旧名的 SQL 失效 |
| 删除列 | 否 | 元数据中移除该字段 | 下游查询直接报错 |
| 分区演进 | 否 | 只影响新写入 | 历史文件按原布局读取 |
不用重写数据不等于没有代价:结构变更会立刻影响所有下游 SQL,改名前先广播影响面,确认主要消费方都已就绪。
删除列之后,元数据里不再保留该字段,重新添加同名列不会自动关联回历史数据。只是暂时不用的话,保留列比删除更安全。