来源 | https://tabular.io/blog/whats-new-in-iceberg-0.13/
作者 | Ryan Blue (Apache Iceberg PMC)
翻译 | liliwei
Apache Iceberg 社区刚刚发布了 0.13 版,其中有很多很棒的新增功能!在这篇文章中,我将介绍一些本版本的亮点功能。
完善对多个引擎支持
Iceberg 0.13 增加了对 Spark 3.2 和 已支撑的 Flink 版本(1.12-1.14)的支持。Spark 和 Flink 都进行了重大改进,我们很高兴能够能够支持它们的最新版本。稍后我将详细介绍这些新功能,但首先我想指出社区如何改进对引擎所有版本的支持方式。
在 0.13 版本之前,社区通过在 Spark 或 Flink 的不同版本之间共享同一个模块来保持兼容性,这就是iceberg-spark3-runtime
模块能同时适用于 Spark 3.0 和 3.1 的原因。总体而言,这种方式虽然减少了我们的代码规模,但带来了太多令人头疼的问题。例如,要在多个 Spark 版本中使用同一个 Jar,Iceberg 必须使用垫片类( shim classes )和反射来调用正确的 Spark 方法。比这个更糟糕的是,要实现新功能变得更加困难,因为它并非包含了每个受支持的版本所需的接口。
在这条道路上,Iceberg 面临着一个糟糕的权衡:必须放弃旧版本以支持新功能。
相反,社区最终决定为每个引擎版本维护一个新模块。这虽然会产生大量的重复代码,但使支持新功能变得更加容易。而且还通过使用编译时验证( compile-time validation )替代反射调用使 Iceberg 更加可靠。
这种支持 Spark 的新结构来得恰如其时。对Spark 3.2 版本的支持向前迈出了一大步,主要体现在支持 Iceberg 声明式数据工程愿景的特性上。
声明式数据工程
声明式数据工程( declarative data engineering )是一种(不是很原始的)理念,您应该告诉您的数据基础设施要做什么,而不是如何做。同样的原则也存在于许多其他框架中,并且在DevOps领域非常普遍。有趣的是,SQL 正是一种声明性语言——但问题是在数据工程中 SQL 没有被以声明式的方式进行使用。
例如,考虑一个简单的SQL,它将数据加载到类似 Hive 的表中:
INSERT INTO logs
SELECT event_ts, level, message,
date_format(event_ts, 'yyyy-MM-dd') as event_day
FROM log_source
ORDER BY date_format(event_ts, 'yyyy-MM-dd'), event_ts
请注意用于分区的新列:event_day
。Iceberg 所做的早期改进之一是使用隐藏分区进行分区声明。在 Iceberg 中,表被配置为 使用 days(event_ts)
自动分区的。读取方无需使用额外的谓词告诉 Spark 如何查找文件。而且写入方无需告诉 Spark 如何派生分区值。
这种方法是一个很大的胜利。你注意到上面插入的错误了吗?它使用本地时区,所以当我在笔记本电脑上运行它时,它会将数据插入错误的分区。哎哟! 隐藏分区不会发生这种情况。
可配置聚类和排序
Spark 3.2 增加了对表请求分布和排序的支持,Iceberg 0.13 使用此功能以声明化表的写时聚类和排序。当前,插入、更新、合并和删除可使用在表内配置的写入顺序。
这解决了需要添加全局 ORDER BY
以避免创建太多小文件的问题。写入分桶表将自动聚集数据以减少创建的文件数量和内存消耗。
要使用这一特性,只需设置表的写入顺序:
ALTER TABLE logs WRITE ORDERED BY event_ts
结合隐藏分区和表写入顺序,上文中的插入操作看起来好多了:
INSERT INTO logs SELECT event_ts, level, message FROM log_source
可以想象,声明式模式的好处会随着时间的推移而俞加明显。如果您想将示例表按日志级别分区,那么运行一个简单的 DDL 语句,Iceberg 将自动获取配置变更并对新的数据生成正确的聚类。无需更改之前的代码!
优化合并和更新
MERGE
和 UPDATE
命令对于声明性数据工程很重要,因为它们提供了一种灵活的方式来告诉 Spark 对各别行进行指定更改,而无需手动读取、连接、过滤和覆盖表的部分数据来完成相同的任务。因 Spark 不支持 MERGE
和 UPDATE
,Iceberg 社区维护了一个添加了这些命令的SQL扩展模块。Spark 3.2 发布的一些特性有助于使这些命令更加原生。
首先,Iceberg 0.13 当前实现了一个用于动态修剪的新接口。动态修剪使用连接关系来创建额外的过滤器并将其下推到表中。这在运行大型关联时非常有用,例如用于 MERGE
语句。在旧版本中,Iceberg 对 MERGE
使用了自定义的动态修剪,但 3.2 及更高版本之后,将使用 Spark 原生特性进行 MERGE
。更好的消息是,这些更新还为 Iceberg 表的所有关联操作添加了动态修剪,而不仅仅是 MERGE
和 UPDATE
。
MERGE
、UPDATE
和 DELETE
为请求分布和排序也进行了全面优化,从而更好地支持表的多分区,并使用元数据列来最小化数据变更。
元数据列也是 Spark 3.2 中的一项新特性,允许选择每一行的元数据,例如源数据文件 ( _file) 及其位置 ( _pos)。
增量删除
Iceberg v2 添加了包含软删除的删除文件——这些文件告诉读取方要跳过的已被替换或删除的行。删除文件可用于进行更有针对性的更改,避免仅仅为了更新或删除几行数据而重写整个大文件(即减少“写放大”)。v2 规范于去年最终定稿并启用,Spark和Flink都增加了新的应用。
0.13 添加了针对 DELETE FROM
的新 Spark 特性实现,它增量删除而不是重写整个数据文件。对于那些想要立即软删除行并累积这些删除以减少大的(昂贵的)重写的人来说,这应该是一个巨大的帮助。
同样,0.13 使用 0.12 中添加的表标识符字段( identifier fields )向 Flink 添加了 UPSERT
支持。
更多
新版本中还有更多内容,我无法一一在此列举,例如数据存储过程、删除压实以及与云提供商的新集成方式。查看完整发行说明。
感谢为 0.13 版本的达成做出贡献的 90 多位贡献者!
转自
声明:本文已获得原作者授权,转载请注明出处。