3、表格式规范详解:Iceberg v1 vs v2规范,列式存储与行级删除的核心区别

聊到Iceberg的表格式规范,很多初学者容易把v1和v2当成两个完全不同的东西。其实没那么复杂。我个人习惯把v1看作「基础版」,v2则是「增强版」。它们共享同一套列式存储骨架,但在行级删除和元数据管理上,v2做了关键升级。

今天我们就掰开揉碎,看看这两个版本到底差在哪。

3.1 列式存储:v1和v2的共享基石

先说共同点。无论是v1还是v2,底层数据文件都采用列式存储格式——Parquet、ORC或Avro。列式存储的好处,说白了就是按需读取。你想想看,一个表有100列,但查询只用到3列,行式存储得把整行数据都扫一遍,列式存储只读那3列的数据块,I/O开销直接降一个量级。

我在项目中遇到过这样一个场景:某张用户行为表有80多列,业务方每天跑聚合查询只取5个字段。改用Iceberg + Parquet后,查询耗时从分钟级降到秒级。嗯,这就是列式存储的威力。

核心要点:Iceberg v1和v2在数据文件层面完全兼容。v2新增的功能不会改变底层列式存储的物理格式,只是在上层元数据中增加了新的文件类型和操作语义。

3.2 v1规范:简单够用,但有硬伤

v1规范是Iceberg的初始版本,设计目标很明确——解决Hive表格式的痛点。它提供了快照隔离、分区演进和隐藏分区这些核心能力。

但v1有个明显的短板:不支持行级删除。这意味着什么?

  • 如果你要更新或删除某几行数据,v1只能重写整个数据文件
  • 对于频繁的小范围更新,会产生大量小文件
  • Merge-on-read场景下,性能会急剧下降

我曾经帮一个金融客户排查数据管道延迟问题。他们的风控表每天有上千万条记录,但只更新其中几千条。用v1规范时,每次更新都要重写整个Parquet文件,数据文件从几十个膨胀到上千个。嗯,这就是典型的「小文件灾难」。

3.3 v2规范:行级删除的救星

v2规范的核心改进,就是引入了删除文件(Delete Files)的概念。它把更新和删除操作从「重写数据文件」变成了「追加删除记录」。

具体来说,v2支持两种删除文件:

删除文件类型 描述 适用场景
Position Delete 按文件路径 + 行号标记删除 精确删除,性能最优
Equality Delete 按字段值匹配删除 按业务主键删除,灵活性高

这两种删除文件,本质上都是小型的列式文件,记录哪些数据行「被标记为已删除」。查询时,Iceberg会合并数据文件和删除文件,过滤掉已删除的行。

我的建议:如果业务场景以批量覆盖为主(比如每天全量同步),v1完全够用。但如果涉及频繁的CDC流式更新或单行修正,直接上v2,别犹豫。我曾经在流式入湖项目中用v2,删除文件的体积通常只有数据文件的1%~5%,性能提升非常明显。

3.4 核心区别对比:一张表说清楚

我把v1和v2的关键差异整理成了一张表,方便你对照:

对比维度 v1规范 v2规范
行级删除 不支持,需重写数据文件 支持,通过删除文件实现
数据文件格式 Parquet / ORC / Avro 同上 + 删除文件(列式)
快照隔离 支持 支持(增强)
分区演进 支持 支持
Merge-on-read 性能差(全量重写) 性能优(增量删除)
元数据版本 v1元数据格式 v2元数据格式(新增删除文件清单)
兼容性 所有Iceberg引擎支持 需要引擎支持v2(Spark 3.x+、Flink 1.14+)

3.5 行级删除的底层原理

这里我展开讲讲v2的行级删除到底怎么工作的。你可能会问:「删除文件不会让查询变慢吗?」

答案是:会,但可控。

查询时,Iceberg的流程是这样的:

  1. 读取快照中的Manifest列表,找到所有数据文件和删除文件
  2. 对每个数据文件,检查是否有对应的删除文件
  3. 如果有,读取删除文件中的行号或键值
  4. 在读取数据文件时,跳过被标记删除的行

这个过程中,删除文件通常很小(只记录被删除的行),所以额外I/O开销有限。但如果删除文件积累太多,查询时合并的开销就会上升。这时候就需要做压缩(Compaction)——把数据文件和删除文件合并,生成新的数据文件,清理掉旧的删除文件。

避坑指南:我曾经在一个实时写入的场景中,忘记配置自动压缩策略。结果删除文件越积越多,查询延迟从200ms飙升到5秒。后来我设置了每1小时或每100个删除文件触发一次压缩,才把性能稳住。记住:行级删除不是银弹,配套的压缩策略必须跟上。

3.6 知识体系总览

下面这张SVG图,把v1和v2的差异、行级删除的流程、以及压缩的关系串起来了:

Iceberg v1 vs v2 核心差异与行级删除流程 Iceberg v1 vs v2 核心差异与行级删除流程 v1 规范 • 数据文件:Parquet / ORC / Avro • 更新方式:重写整个数据文件 • 小文件问题:频繁更新导致文件膨胀 • 适用场景:批量覆盖、低频更新 v2 规范 • 数据文件 + 删除文件 • 更新方式:追加删除记录 • 删除文件类型:Position / Equality • 适用场景:CDC流式、单行修正 升级 v2 行级删除查询流程 读取Manifest列表 匹配删除文件 读取删除记录 跳过已删行 返回结果 压缩(Compaction)时机 • 删除文件数量超过阈值(如100个) → 触发压缩 • 查询延迟明显上升 → 检查删除文件堆积情况

3.7 选型建议

最后,结合我自己的经验,给你几个选型建议:

  • 新项目直接上v2:现在主流引擎(Spark 3.2+、Flink 1.14+、Trino)都支持v2,没必要走回头路
  • 存量v1表迁移要谨慎:v2不向下兼容v1的元数据格式,迁移需要重写元数据。我建议先在小表上验证,再逐步推广
  • 关注删除文件的膨胀速度:如果业务以插入为主、极少更新,v2的优势不明显,v1反而更简单