Apache Iceberg 1.12.0 发布
DataHot 速览
Apache Iceberg 社区发布 1.12.0,自 1.11.0 以来包含 142 位贡献者的 777 次提交。该版本提升 Variant 读取性能,并将 shredded Variant 写入扩展到 Spark 之外,支持 Flink、Kafka Connect sink 和通用记录写入器。它还为 geometry 和 geography 地理空间类型增加读写支持,并以 WKB 存储在 Avro 和 Parquet 中。版本包含多项 Variant 正确性与健壮性修复,如 UTF-8 边界、指标崩溃和大十进制分片等。
为什么值得关注:Iceberg 是湖仓开放表格式的核心项目,本次更新涉及半结构化数据性能、多引擎写入和地理空间类型,直接影响数据平台选型与接入效率。
本文目录 17 节
译文
AI 逐段翻译Apache Iceberg 社区很高兴地宣布 Apache Iceberg 1.12.0 发布。此版本是777 次提交的结果,来自142 位贡献者自 1.11.0 以来的工作。请参阅发行说明以获取完整的更改列表。
版本亮点🔗
数据类型:Variant 和 Geospatial🔗
此版本改进了 Variant 读取性能,将 shredded Variant 写入扩展到 Spark 之外,并增加了对 geospatial 类型的读取和写入支持。
Variant。在 Spark 中读取未 shredded 的 Variant 数据现在更快了。在 Spark 4.0 和 4.1 上,未 shredded 的 Variant 列通过向量化 Parquet 路径读取,而不是逐行解码。
Variant shredding 还使用了更严格的布局规则。Shredding 现在要求类型一致性:只有当某个字段的所有值都属于单一类型族(经过数值拓宽后)时,该字段才会被 shred 为类型化列;混合类型的字段保留在无类型残留中。与之前基于多数的规则不同(该规则可能在仅覆盖字段一小部分行的情况下将其 shred),现在每个类型化列都完全覆盖其字段。单一类型字段不受影响。
Shredded Variant 写入不再仅限 Spark。Flink 现在可以写入 shredded Variant,并且Kafka Connect sink 和通用记录写入器也可以生成 shredded Variant,因此通过这些路径摄取的半结构化数据也能受益于相同的读取时下推。Flink 还获得了Avro 读取器和写入器中的 Variant 支持。
Variant 还包含若干正确性和加固修复:
- Shredded 列的字符串边界以UTF-8 字节顺序计算,二进制上界向上截断,从而保持修剪正确;边界还遵循该列配置的截断长度
- 修复了为无统计信息的值列计算指标时崩溃的问题,并大十进制 shredding(精度 > 18)已得到修正
- Variant 类被设置为可序列化,二进制解析已针对畸形输入加固
- 对包含 Variant 列的表进行 ORC 过滤器下推的问题已修复
Geospatial。 geometry 和 geography 类型获得了读取和写入支持。两者都以 Well-Known Binary (WKB) 存储,现在可以在 Avro 中读取和写入以及在 Parquet 中读取和写入,在 Parquet 中它们映射到Parquet geometry 和 geography 逻辑类型,因此文件是自描述的;单值二进制序列化也已就位,用于默认值和元数据。
Spark 4.1是首个具有端到端 geospatial 路径的引擎:它在 Parquet 中读写这两种类型,并支持对包含 geospatial 列的表进行行级DELETE、UPDATE 和 MERGE,包括格式版本 3 上的 merge-on-read、删除向量路径。当前限制:
- 支持仅限于 Spark 4.1(不支持 Spark 3.5 或 4.0、Flink 或 ORC)
- 读取使用基于行的读取器;尚无 Arrow geospatial 向量
- 尚无空间谓词,因此过滤器是针对非 geospatial 列表达的
删除向量🔗
删除向量获得了通过以下方式进行的共址访问DataFile.deletionVector(),并修复了共享 Puffin 文件时的引用以及合并时保留加密元数据的问题。
流式删除🔗
向 Iceberg 执行 upsert 的流式管道会写入等值删除:这些标记表示“删除键与这些值匹配的每一行”。它们写入成本低但读取成本高,因为每个查询都必须重新打开数据文件并比较值,以确定哪些行仍然存在。1.12.0 添加了一个 Flink 原生维护任务,可一次性解析这些删除,而不是在每次扫描时解析。
ConvertEqualityDeletes。这个新的维护任务将流式摄取期间产生的等值删除解析为行位置删除向量,并将其与数据文件一起提交。转换后,读取器按位置应用删除,而不是重新扫描并比较值,因此查询不再承担此成本。
它与 IcebergSink 配合使用,后者在源分支上暂存新数据文件和等值删除;转换器将这些解析为删除向量并提交到目标分支,或就地转换。由于删除向量是 v3 功能,该任务要求表格式版本 3 或更高版本,并运行在 Flink 1.20、2.1、2.2 和 2.3 上。它通过多项变更落地,包括核心数据模型和与 IcebergSink 的集成;后续确保删除的行在转换周期失败后不会重新出现。
数据布局🔗
Hilbert 聚类。 rewrite_data_files 新增Hilbert 曲线聚类,这是与 Z-order 并列的一种新的多维排序策略。两者都将多个列映射到单条空间填充曲线上,以便这些列中值相似的行存储在一起,从而改进多列过滤器的文件跳过。Hilbert 使曲线上的相邻点在数据中保持相邻,而不会出现 Z-order 在空间中产生的大幅“跳跃”。你可以通过排序策略选择它:
CALLsystem.rewrite_data_files(table=>'db.tbl',strategy=>'sort',sort_order=>'hilbert(c1, c2)');Hilbert 聚类随 Spark 4.1 提供。
其他维护。 RepairTable 操作接口已定义(一种标准方式,用于修复与其描述的文件不一致的清单项统计信息),并且 Spark 的rewrite_data_files 现在接受 max-file-group-input-files 选项,以限制单个组中的输入文件数量。
REST Catalog🔗
REST catalog 协议新增了若干内容,这里按层次分组。(对 loadTable 的更细粒度读取限制属于规范级变更,将在下方的规范演进中介绍。)
OpenAPI 协议。 VariantType现在可以在规范中表示,因此 Variant 列可以通过协议随 schema 传输。新增只读列出和加载函数端点以及一个unregister-table 端点(将表从 catalog 分离而不删除其数据或元数据),此外还有形式化的远程签名配置和用于 catalog 元数据丰富化的 labels 字段。
库和客户端。 CatalogObjectIdentifier增加了一种为 catalog 对象命名的共享方式,远程签名配置获得了客户端实现,并且 catalog 标签会在加载响应中读取并通过 SupportsLabels 在加载的表上暴露。
规范演进🔗
在此次发布中,规范与代码同步演进。这些变更定义了当前及未来表版本的行为;它们不一定是 1.12.0 中已发布的引擎功能。
该表达式规范已被采纳,为 Iceberg 提供了正式的、与引擎无关的谓词表达式定义;REST OpenAPI 规范已对其对齐,在同一发布中,因此读限制行过滤器可跨客户端移植。
更细粒度的读限制在 loadTable 上被添加:目录可以在加载响应中返回一个 ReadRestrictions 对象,描述所需的列投影(列掩码操作,例如仅显示最后四个字符、将值替换为 null、截断时间戳、哈希或字母数字掩码),以及一个建模为 Iceberg 表达式的必需行过滤器。该契约由客户端强制执行且故障关闭:支持读限制的读取器必须完整应用每个返回的操作和过滤器,如果无法应用其中一个,则必须使查询失败,而不是返回原始、部分或空行。这仅是规范和 OpenAPI 契约;在 1.12.0 中没有任何 Iceberg 读取器会应用读限制,因此今天返回 ReadRestrictions 对象的目录会被每个消费者静默忽略。
内容文件唯一性现在已明确规定:在一个快照内,每个内容文件在所有清单中最多只能被一个活跃清单条目引用,违反此规则的快照行为未定义。更小的澄清完善了规范工作:Variant 类型分类和 decimal 类型序列化。
格式 V4 基础🔗
面向表格式 V4 的工作仍在继续。V4 正在积极开发中,尚未被正式采纳:Iceberg 1.12.0 无法读取或写入 V4 表,此处的一切都是下一个被批准的规范版本将构建于其上的基础工作。
清单。 此发布添加了一个 V4 清单读取器,可读取以 Parquet 和 Avro 两种格式写入的 V4 清单,以 V4 布局写入 Parquet 和 Avro 清单的能力,以及一个 适配器层,带有 受跟踪文件元数据模型,通过现有的 ManifestFile 和 DataFile 接口呈现 V4 跟踪的文件。这些在清单级别运行,用于测试和未来使用;表仍然无法在 V4 中创建或提交。
基础。 若干结构性部件落地:元数据中的相对路径(由 相对化工具和 读取端解析支持),这是迈向可重定位表的一步;一个新的 内容统计规范补充;以及 Mumbling bitmap 的只读实现,这是一种用于删除向量等场景的有界大小压缩位图格式,基于 Roaring Bitmap。
性能与可靠性🔗
更快的规划和扫描。 清单列表文件现在被缓存在清单内容缓存中,并且 Parquet 获得了 自适应布隆过滤器大小和 按列字典编码。
向量化读取器修复。 向量化 Parquet 读取器获得多项正确性修复:int 到 long 提升(此前会抛出 ClassCastException)、带默认值的 decimal 列、精度大于 18 的 decimal、字典编码的 VARCHAR/VARBINARY 通过直接字节缓冲区、全 null 的 DELTA 编码页、一个 INT96 字典解码偏移,以及一个 行谱系读取器中的直接内存泄漏。
更精准的剪枝。 纳秒时间戳上的谓词下推已在 Parquet 和 ORC 中修复,notStartsWith 不再跳过包含 null 的行组,并且对于在写入时未带 null_count 的 Parquet 文件,null 计数是正确的。
核心修复。 FileIO 泄漏已修复,并且 close() 在各目录实现中已标准化,浮点值的 Z-order 字节编码已更正,EncryptingFileIO 被重构为 DelegateFileIO,以便加密表保留对底层 I/O 能力的访问,例如批量操作,并且一个 清单剪枝和残差求值 bug 已被解决。
安全🔗
此发布通过 jackson-databind 修复了两个 HIGH 严重性 CVE,CVE-2026-54512 和 CVE-2026-54513,方法是 在各运行时和捆绑包中对齐 Jackson 版本;进一步的 Jackson 升级 修复了 GHSA-r7wm-3cxj-wff9。Kafka Connect 运行时中仍存在三个 Jackson 发现,因为它们来自 parquet-jackson 内部 shaded 的 Jackson 副本,无法独立于 Apache Parquet 升级。
已清理 shaded-jar LICENSE 和 NOTICE 文件:从 cloud 和 engine 捆绑包中剥离了重复的许可证元数据,并添加了缺失的第三方声明。
引擎更新🔗
Spark🔗
1.12.0 中的 Spark 支持为 Spark 3.5、4.0 和 4.1;Spark 3.4 支持已被移除。值得注意的新增内容:
- 委托 PURGE:
DROP TABLE ... PURGE可以 委托给 REST catalog 通过rest-catalog-purge属性,在 Spark 3.5、4.0 和 4.1 上 - 容错迁移:
snapshot和migrate过程接受ignore_missing_files - 按排序键重写清单:
rewrite_manifests过程获得一个sort_by参数在 Spark 3.5 和 4.0 上,与 Spark 4.1 匹配 - 流式合并追加:一个 写入配置为 Structured Streaming 写入启用合并追加,已移植到 Spark 3.5 和 4.0
Spark 4.1 还获得了地理空间支持(在上文数据类型部分描述),以及用于 rewrite_data_files 的 Hilbert 曲线聚类(在上文数据布局部分描述)。
Flink🔗
1.12.0 中的 Flink 支持为 Flink 1.20、2.1、2.2 和 2.3;新增了 Flink 2.2 和 2.3,移除了 Flink 2.0。
除上述等值删除到位图向量转换之外,Flink 还获得了 Iceberg 视图支持:它可以 在 SQL 中读取视图 并 创建、删除和重命名它们 通过 FlinkCatalog(两者都已回移到 2.2、2.1 和 1.20)。
Dynamic Sink 获得了 细粒度 slot-sharing-group 控制 以及若干修复:
Kafka Connect🔗
sink 连接器现在 会暴露提交失败而不是吞掉它们,添加了 对瞬时提交异常的有界重试 以及一个 用于部分提交失败的指标,并通过以下方式改进了偏移处理:仅提交大于现有偏移的偏移 和 将控制主题偏移量跟踪为高水位标记。
破坏性变更🔗
从 1.11.0 升级的用户应在升级前查看这些内容。
已移除:
- 移除 Spark 3.4:Spark 3.4 支持已被移除;请使用 Spark 3.5、4.0 或 4.1
- 移除 Flink 2.0:Flink 2.0 支持已被移除(新增了 Flink 2.2 和 2.3),因此 1.12.0 支持 Flink 1.20、2.1、2.2 和 2.3
- 移除携带行数据的位置删除文件:写入携带行数据的位置删除已被移除,与格式版本 3 中转向删除向量保持一致
DataReader已移除:已移除,改用PlannedDataReader
已弃用 API 已移除:
- 分区统计信息读取功能(请使用 Partition Stats Scan API)
- Spark
SparkFilters、SparkTableUtil方法,以及SparkReadConf/SparkWriteConf/SparkSchemaUtil方法 - Data
GenericAppenderFactory和BaseFileWriterFactory - AWS S3 签名器类和属性
- Flink
RewriteDataFiles.Builder.filter(Expression) - Core REST 命名空间编码辅助工具 以及
HadoopFileIO(SerializableSupplier)构造函数 - Kafka Connect
TableReference和IcebergWriterResult成员 - BigQuery catalog 属性常量
- 对计划在 1.12.0 中移除的方法和字段的最后一次清理计划在 1.12.0 中移除的方法和字段的最终清理
行为变更:
- AWS HTTP 客户端:默认的 AWS SDK HTTP 客户端已迁移到 Apache HttpClient 5;自行管理 AWS SDK 类路径的用户(即直接使用
iceberg-aws而非iceberg-aws-bundle的用户)必须从software.amazon.awssdk:apache-client切换到software.amazon.awssdk:apache5-client - 地理空间
toString():GeometryType和GeographyTypetoString()现在包含解析后的 CRS,对于 geography 还包含边缘算法(例如geometry(OGC:CRS84)和geography(OGC:CRS84, spherical)),而不是仅使用类型名称 - REST 幂等重试:REST 客户端现在会对携带
Idempotency-Key的 POST 请求在可重试错误(408、500、502、503、504)时进行重试
依赖更新🔗
1.12.0 中值得注意的依赖更新:
- AWS SDK (bom):2.44.4 -> 2.54.17
- Jackson (bom):2.21.3 -> 2.22.2
- Netty:4.2.13.Final -> 4.2.18.Final
- Nessie:0.107.5 -> 0.108.8
- RoaringBitmap:1.6.14 -> 1.6.23
- Avro:1.12.1 -> 1.12.2
- ORC:1.9.8 -> 1.9.9
- Guava:33.6.0-jre -> 33.7.1-jre
- Caffeine:2.9.3 -> 3.2.4
参与其中🔗
Apache Iceberg 由贡献者社区开发。我们使用 GitHub issues 来跟踪工作,并使用 Apache Iceberg Community Slack 进行讨论。
最简单的入门方式是:
- 在您的工作负载中试用 Apache Iceberg 1.12.0,并报告您遇到的任何问题
- 查阅 贡献者指南
- 寻找 good first issues
如需更多信息,请访问 Apache Iceberg 仓库 或 文档。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏