Iceberg 表格式核心概念:快照、清单、数据文件、分区
聊 Iceberg 的表格式,说白了就是搞清楚它怎么管数据的。我第一次接触时也被一堆术语搞晕过——快照、清单、数据文件,还有分区。后来在线上环境踩过几次坑,才真正理解这些概念的设计意图。
今天我把这四个核心概念拆开讲。你理解透了,后面学数据共享、时间旅行这些高级功能就顺了。
1. 数据文件(Data File)——最底层的存储单元
数据文件是 Iceberg 里真正存数据的地方。Parquet、ORC、Avro 都行,我个人最常用 Parquet,列存 + 压缩,查询性能好。
每个数据文件都记录了:
- 文件路径(存在哪个目录下)
- 文件格式(Parquet/ORC/Avro)
- 行数、大小
- 列统计信息(最小值、最大值、空值数)
- 分区信息
关键点:数据文件一旦写入就不可变。Iceberg 不会原地修改文件,只会追加新文件或标记旧文件为删除。这保证了并发读写的一致性。
举个例子,你往一张订单表里插入 100 万条数据,Iceberg 不会去改已有的文件,而是生成一个新的 Parquet 文件。旧文件还在,只是新快照不再引用它。
2. 清单(Manifest)——数据文件的索引
清单是什么?说白了就是数据文件的「目录」。每个清单文件(manifest file)里存着一组数据文件的元信息。
我习惯把清单理解成「分片索引」。一个清单可能管理几百个数据文件,每个文件的信息都列在里面。
清单文件本身也是不可变的,用 Avro 格式存储。它包含:
- 数据文件的状态(新增/删除/存在)
- 分区范围
- 列统计信息的聚合
- 文件级别的元数据
小技巧:查询时 Iceberg 会先读清单,利用统计信息跳过不相关的数据文件。这就是「分区裁剪 + 文件裁剪」的核心机制。我曾经帮一个团队优化慢查询,加了分区后查询时间从 5 分钟降到 10 秒,靠的就是清单里的统计信息做文件级过滤。
3. 快照(Snapshot)——表的时间点视图
快照是 Iceberg 最巧妙的设计之一。每个快照代表表在某个时刻的完整状态——它指向一组清单文件,这些清单文件又指向所有活跃的数据文件。
你可以把快照想象成 Git 的 commit。每次写入、删除、合并操作都会生成一个新快照。旧快照不会立即删除,所以你能回溯到任意历史时间点。
| 操作 | 快照行为 | 旧数据 |
|---|---|---|
| INSERT | 生成新快照,追加新文件 | 保留 |
| DELETE | 生成新快照,标记旧文件删除 | 保留(快照隔离) |
| UPDATE | 生成新快照,删除旧文件 + 追加新文件 | 保留 |
| COMPACT | 生成新快照,合并小文件 | 保留(直到过期) |
注意:快照不会永久保留。Iceberg 有快照过期策略,默认保留最近 10 个快照。如果你需要长时间保留历史数据做时间旅行,记得调大 snapshot.expire.older-than 参数。我曾经因为没配这个参数,导致某次数据回溯查不到 3 天前的状态,排查了半天才发现是快照被自动清理了。
4. 分区(Partition)——物理与逻辑的分离
Iceberg 的分区和 Hive 分区有本质区别。Hive 的分区是目录结构,比如 /dt=2024-01-01/,查询时靠目录名过滤。Iceberg 的分区是「隐藏分区」——分区信息存在元数据里,不依赖目录结构。
这意味着:
- 你可以随时改变分区策略,不需要重写数据
- 分区字段可以是计算列(比如
month(ts)) - 查询时自动做分区裁剪,不需要用户指定分区条件
举个例子,你有一张表按天分区,后来业务变了想按月分区。Hive 你得重建表、重导数据。Iceberg 只需要改分区配置,新数据自动按新规则分区,旧数据还是按旧规则存,查询时 Iceberg 自动处理。
核心差异:Iceberg 的分区是逻辑概念,不是物理目录。分区信息存在清单文件里,和数据文件路径无关。这才是真正的「分区透明」。
5. 四者关系:一张图看懂
下面这张图展示了快照、清单、数据文件、分区之间的关系。我画的时候特意把层级关系标清楚了。
6. 实战:这些概念怎么配合工作?
假设你有一张电商订单表,按 order_date 分区。执行一次 INSERT 操作时,Iceberg 内部发生了什么?
- 写入数据文件:新数据按分区规则写入 Parquet 文件,比如
/data/order_date=2024-06-01/0001.parquet - 生成清单:创建一个新的清单文件,记录这个数据文件的路径、行数、统计信息
- 创建新快照:生成一个新的快照,指向最新的清单文件列表(包含刚才创建的清单)
- 更新元数据:更新表的元数据文件,指向最新的快照
整个过程是原子性的。如果写入失败,元数据不会更新,表的状态不变。这就是 Iceberg 的 ACID 保证。
避坑指南:我曾经在生产环境遇到一个问题——小文件太多导致查询变慢。原因是每次写入都生成新文件,没有做 compaction。解决方案是定期执行 OPTIMIZE TABLE 合并小文件,同时清理过期快照释放存储。记住,快照隔离虽然好用,但别让快照无限增长。
7. 总结一下
这四个概念是 Iceberg 的基石:
- 数据文件:存真实数据,不可变
- 清单:管理数据文件的索引,支持文件级裁剪
- 快照:表的时间点视图,支持时间旅行
- 分区:逻辑分区,不依赖目录结构,灵活变更
理解它们之间的关系,你就掌握了 Iceberg 的核心设计哲学。后面讲数据共享、增量读取、跨引擎查询时,你会发现这些概念无处不在。