首页/数据/数据工程与 ETL 速查/Schema 演进与兼容性
管道基础52 条

Schema 演进与兼容性

上游加字段、改类型在数据链路里不可避免。基本原则:加带默认值的字段通常向后兼容,删字段要带默认值保证旧读兼容,改类型(除数值提升)通常不兼容。

Schema 演进是什么

上游库加字段、改类型、删字段,在长期运行的数据链路里不可避免,schema 演进就是约定「这些变更发生时,新旧数据还能不能互相读得懂」。判断标准分两个方向:向后兼容指新 schema 能读旧数据,向前兼容指旧 schema 能读新数据。多数格式(Avro、Parquet、Iceberg)都支持按字段名解析、缺失字段取默认值,但类型变更和重命名通常需要额外配置。

基本信息

向后兼容新 schema 读旧数据,新增字段取默认值
向前兼容旧 schema 读新数据,删除字段需保留旧默认值
不兼容类型变更、字段重命名,除非显式开启字段映射
定位方式列式文件按字段名定位,CSV 等按顺序定位
治理手段schema registry、变更卡口、上下游字段契约

Hive 加列(CASCADE 同步到分区)

Hive 加列(CASCADE 同步到分区)
ALTER TABLE dwd_order ADD COLUMNS (channel STRING COMMENT '下单渠道') CASCADE;

-- 查看变更后的表结构确认生效
DESCRIBE FORMATTED dwd_order;

-- 指定分区的元数据也要一并刷新
MSCK REPAIR TABLE dwd_order;

Avro 兼容变更示意

Avro 兼容变更示意
{"name": "channel", "type": ["null", "string"], "default": null}

典型使用场景

  • 业务库加了一列,ODS 到明细层要同步加列并让历史分区可读
  • Kafka 消息体新增可选字段,消费者要能在字段缺失时用默认值兜底
  • 删除废弃字段前先确认没有任何下游仍在读取它
  • 跨格式转换(Avro 存 Kafka、Parquet 存湖)时要按目标格式的规则校验兼容性
  • 接入 schema registry 后由注册中心拒绝不兼容变更,把问题拦在上游

变更类型与兼容性

变更兼容性前提
新增带默认值的字段通常向后兼容读取方按名称匹配并接受默认值
新增无默认值的字段读旧数据会失败或取空必须指定默认值
删除字段对旧读取方可能不兼容旧 schema 侧保留默认值
数值类型提升(int 到 long)多数格式允许反方向收窄通常不允许
字段重命名默认不兼容需开启字段映射或做别名处理
列式文件按名字定位字段,但 CSV/位置绑定格式按顺序读;链路里要明确字段顺序约定,一旦上游在中间插入字段,按位置解析的下游会整体错位。
改类型前先评估下游读取方:多数引擎不会自动做回退转换,遇到不匹配会直接读失败而不是取空值。稳妥做法是新增一列新类型字段,由双写过渡一段时间后再下线旧列。

易错点

  • Hive 加列不加 CASCADE 时,旧分区读不到新列(表现为 null)
  • 改字段类型前先评估下游:多数引擎不会自动回退转换,会直接读失败
  • 以为 Parquet 自带 schema 就万事大吉,实际上采样出的 schema 会随新文件行数变化而漂移
  • 重命名字段只改了上游,下游 SQL 里的旧字段名会直接报字段不存在
  • 向下兼容的字段删除没有过渡期,历史数据回溯任务会突然失败

数据来源与参考

  • Apache Avro 官方文档:Schema Resolution
  • Apache Hive LanguageManual DDL:ALTER TABLE ADD COLUMNS
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌