通用格式 (UniForm)
Delta通用格式(UniForm)允许您使用Iceberg和Hudi客户端读取Delta表。
UniForm 利用了Delta Lake、Iceberg和Hudi都由Parquet数据文件和元数据层组成这一事实。UniForm会异步自动生成Iceberg元数据,使Iceberg客户端能够像读取Iceberg或Hudi表一样读取Delta表。启用UniForm后,Delta写入开销可以忽略不计,因为元数据转换和事务是在Delta提交后异步进行的。
数据文件的单一副本可提供给所有格式的客户端访问。
启用Delta Lake UniForm
重要
启用Delta UniForm Iceberg需要Delta表功能IcebergCompatV2,这是一个写入协议功能。只有支持此表功能的客户端才能写入已启用的表。您必须使用Delta Lake 3.1或更高版本来写入启用了此功能的Delta表。
启用Delta UniForm Iceberg需要在Spark shell中提供"delta-iceberg"包:–packages io.delta:io.delta:delta-iceberg_2.12:
启用Delta UniForm Hudi功能需要向Spark shell提供"delta-hudi"包:–packages io.delta:io.delta:delta-hudi_2.12:
以下表格属性支持为Iceberg启用UniForm功能。
'delta.enableIcebergCompatV2' = 'true'
'delta.universalFormat.enabledFormats' = 'iceberg'
以下表格属性支持为Hudi启用UniForm功能。
'delta.universalFormat.enabledFormats' = 'hudi'
以下表格属性支持UniForm对两者的兼容。
'delta.enableIcebergCompatV2' = 'true'
'delta.universalFormat.enabledFormats' = 'iceberg,hudi'
要使用UniForm,您还必须启用列映射。在创建表时会自动设置,如下例所示:
CREATE TABLE T(c1 INT) USING DELTA TBLPROPERTIES(
'delta.enableIcebergCompatV2' = 'true',
'delta.universalFormat.enabledFormats' = 'iceberg');
在 Delta 3.3 及以上版本中,您可以使用以下语法在现有表上启用或升级 UniForm Iceberg:
ALTER TABLE table_name SET TBLPROPERTIES(
'delta.enableIcebergCompatV2' = 'true',
'delta.universalFormat.enabledFormats' = 'iceberg');
你也可以使用REORG来启用UniForm Iceberg并重写底层数据文件,如下例所示:
REORG TABLE table_name APPLY (UPGRADE UNIFORM(ICEBERG_COMPAT_VERSION=2));
在以下任一情况为真时使用REORG:
您的表已启用删除向量。
您之前启用了UniForm Iceberg的IcebergCompatV1版本。
您需要从不支持Hive风格Parquet文件的Iceberg引擎读取数据,例如Athena或Redshift。
您可以使用以下语法在现有表上启用UniForm Hudi:
ALTER TABLE table_name SET TBLPROPERTIES ('delta.universalFormat.enabledFormats' = 'hudi');
注意
该语法要求在Delta 3.1上运行前,需先在表上启用Delta列映射功能。此语法也可用于从IcbergCompatV1版本升级。它可能会重写现有文件使其兼容Iceberg格式,并自动禁用和清除表中的删除向量。
重要
首次启用UniForm时,系统会开始异步生成元数据。在外部客户端能够使用Iceberg或Hudi查询表之前,此任务必须完成。请参阅检查Iceberg/Hudi元数据生成状态。
警告
您可以通过取消设置表属性delta.universalFormat.enabledFormats来关闭UniForm功能。但请注意,一旦启用列映射就无法关闭,且升级Delta Lake读写器协议版本的操作不可逆。
参见限制。
UniForm何时生成元数据?
Delta Lake 在完成写入事务后,会使用相同的计算资源异步触发 Iceberg/Hudi 元数据的生成。
Iceberg/Hudi的写入延迟可能明显高于Delta Lake。频繁提交的Delta表可能会将多个Delta提交合并为单个Iceberg/Hudi提交。
Delta Lake确保在单个集群中,任何时刻每个格式只有一个元数据生成过程在进行。那些会触发第二个并发元数据生成过程的提交虽然能成功提交到Delta,但不会触发异步元数据生成。这可以防止频繁提交工作负载(提交间隔在几秒到几分钟之间)时出现元数据生成的级联延迟问题。
检查Iceberg/Hudi元数据生成状态
UniForm向Iceberg/Hudi表元数据添加以下属性以跟踪元数据生成状态:
表属性 |
描述 |
|---|---|
|
成功生成元数据的最新版本的Delta表。 |
|
成功生成元数据的最新Delta提交的时间戳。 |
有关如何在Delta Lake之外查看表属性,请参阅您的Iceberg/Hudi读取器客户端文档。对于Apache Spark,您可以使用以下语法查看这些属性:
SHOW TBLPROPERTIES <table-name>;
在Apache Spark中将UniForm表作为Iceberg表读取
您可以通过以下步骤在Apache Spark中将UniForm表作为Iceberg表读取:
启动带有Iceberg的Apache Spark,并连接到UniForm所使用的Hive Metastore。关于如何运行带有Apache Spark的Iceberg并连接到Hive Metastore,请参考Iceberg文档。
使用
SHOW TABLES命令查看目录中可用的Iceberg表列表。使用标准SQL(如
SELECT)读取Iceberg表。
使用元数据JSON路径将UniForm表读取为Iceberg表
某些Iceberg客户端允许您通过提供版本化元数据文件的路径来注册外部Iceberg表。每当UniForm将Delta表的新版本转换为Iceberg时,它都会创建一个新的元数据JSON文件。
使用元数据JSON路径配置Iceberg的客户端包括BigQuery。有关配置详情,请参阅Iceberg读取器客户端的文档。
Delta Lake 将 Iceberg 元数据存储在表目录下,采用以下模式:
<table-path>/metadata/v<version-number>-uuid.metadata.json
在Apache Spark中将UniForm表读取为Hudi表
您可以通过以下步骤将UniForm表作为Hudi表在Apache Spark中读取:
查看Hudi文档了解如何在Apache Spark上运行Hudi
spark.read.format("hudi").option("hoodie.metadata.enable", "true").load("PATH_TO_UNIFORM_TABLE_DIRECTORY")
Delta与Iceberg/Hudi表版本
Delta Lake、Iceberg和Hudi都支持使用表版本或存储在表元数据中的时间戳进行时间旅行查询。
Delta和Iceberg表的版本既不会通过提交时间戳对齐,也不会通过版本ID对齐。然而,Delta和Hudi的提交时间戳是对齐的,但版本ID并不对齐。如果您想验证Iceberg/Hudi表的某个特定版本对应的是Delta表的哪个版本,可以使用Iceberg/Hudi表上设置的相应表属性。参见检查Iceberg/Hudi元数据生成状态。
限制
警告
从Iceberg和Hudi的角度来看,UniForm是只读的。然而,这无法强制执行,因为对于Iceberg,UniForm使用HMS作为Iceberg目录;对于Hudi,元数据存储在文件系统上。如果有任何外部写入器(非Delta Lake)向这个Iceberg/Hudi表写入数据,可能会破坏您的Delta表并导致数据丢失,因为Iceberg/Hudi写入器可能会执行Delta不知情的数据清理或垃圾回收操作。
存在以下限制:
UniForm不适用于启用了删除向量的表。请参阅什么是删除向量?。
启用了UniForm的Delta表不支持
VOID类型。Iceberg/Hudi 客户端只能从 UniForm 读取数据,不支持写入操作。
无论是否使用UniForm,Iceberg/Hudi读取器客户端可能存在各自的限制。请参阅您目标客户端的文档。
启用UniForm后,以下Delta Lake功能适用于Delta客户端,但Iceberg不支持这些功能:
变更数据订阅
Delta 共享