在 Iceberg 客户端中使用 UniForm 读取 Delta 表

Delta Lake 通用格式 (UniForm) 允许使用 Iceberg 阅读器客户端读取 Delta 表。 此功能需要 Databricks Runtime 14.3 LTS 或更高版本。

重要

有关旧版 UniForm IcebergCompatV1 表功能的文档,请参阅旧版 UniForm IcebergCompatV1

可以配置外部连接,使 Unity Catalog 充当 Iceberg 目录。 请参阅使用 Unity Catalog Iceberg 目录端点读取

UniForm Iceberg 使用 Zstandard 而非 Snappy 作为基础 Parquet 数据文件的压缩编解码器。

注意

UniForm 元数据生成在用于将数据写入 Delta 表的计算上异步运行,这可能会加剧驱动程序资源使用状况。

UniForm 的工作原理是什么?

UniForm 利用了 Delta Lake 和 Iceberg 由 Parquet 数据文件和元数据层组成的事实。 UniForm 自动异步生成 Iceberg 元数据,而无需重写数据,因此 Iceberg 客户端可以读取 Delta 表。 数据文件的单一副本可用于多种格式。

要求

要启用 UniForm Iceberg,必须满足以下要求:

注意

无法对启用了 UniForm Iceberg 的表启用删除向量。

使用 REORG 禁用和清除删除矢量,同时在启用了删除矢量的现有表上启用 UniForm Iceberg。 请参阅使用 REORG 来启用或升级

启用 UniForm Iceberg

重要

启用 Delta UniForm 将设置 Delta 表功能 IcebergCompatV2,它是写入协议功能。 只有支持此表功能的客户端才能写入启用了 UniForm 的表。 必须使用 Databricks Runtime 14.3 LTS 或更高版本才能在启用此功能的情况下写入 Delta 表。

可以通过取消设置 delta.universalFormat.enabledFormats 表属性来关闭 UniForm。 无法撤消对 Delta Lake 读取器和编写器协议版本的升级。

必须设置以下表属性,才能启用 UniForm Iceberg:

'delta.enableIcebergCompatV2' = 'true'
'delta.universalFormat.enabledFormats' = 'iceberg'

首次启用 UniForm 时,异步元数据生成就开始了。 在外部客户端可以使用 Iceberg 查询表之前,必须完成此任务。 请参阅检查 Iceberg 元数据生成状态

有关限制列表,请参阅限制

在创建表期间启用

必须启用列映射才能使用 UniForm Iceberg。 如果在创建表期间启用 UniForm Iceberg,则会发生这种情况,如下例所示:

CREATE TABLE T(c1 INT) TBLPROPERTIES(
  'delta.enableIcebergCompatV2' = 'true',
  'delta.universalFormat.enabledFormats' = 'iceberg');

通过更改现有表来启用

在 Databricks Runtime 15.4 LTS 及更高版本中,可使用以下语法在现有表上启用或升级 UniForm Iceberg:

ALTER TABLE table_name SET TBLPROPERTIES(
  'delta.enableIcebergCompatV2' = 'true',
  'delta.universalFormat.enabledFormats' = 'iceberg');

使用 REORG 来启用或升级

可以使用 REORG 启用 UniForm Iceberg 并重写基础数据文件,如以下示例所示:

REORG TABLE table_name APPLY (UPGRADE UNIFORM(ICEBERG_COMPAT_VERSION=2));

如果存在以下任一情况,请使用 REORG

  • 你的表已启用删除矢量。
  • 你之前已启用 UniForm Iceberg 的 IcebergCompatV1 版本。
  • 需要从不支持 Hive 样式的 Parquet 文件(如 Athena 或 Redshift)的 Iceberg 引擎中读取。

UniForm 何时生成 Iceberg 元数据?

在 Delta Lake 写入事务完成后,Azure Databricks 会异步触发元数据生成。 此元数据生成过程使用完成 Delta 事务的相同计算。

注意

还可以手动触发 Iceberg 元数据生成。 请参阅手动触发 Iceberg 元数据转换

为了避免与元数据生成相关的写入延迟,频繁提交的 Delta 表可能会将多个 Delta 提交组合到单个 Iceberg 元数据提交中。

Delta Lake 确保在给定计算资源上任何时候都只有一个元数据生成进程在进行中。 触发第二个并发元数据生成进程的提交将成功提交到 Delta,但这些提交不会触发异步 Iceberg 元数据生成。 这可以防止频繁提交的工作负载的元数据生成的级联延迟(提交之间的秒到分钟)。

请参阅 Delta 和 Iceberg 表版本

Delta 和 Iceberg 版本

Delta Lake 和 Iceberg 允许使用存储在表元数据中的表版本或时间戳进行按时间顺序查看查询。

通常,Iceberg 和 Delta 表的版本不按照提交时间戳或版本 ID 对齐。 要验证给定版本的 Iceberg 表对应的 Delta 表版本,可使用相应的表属性。 请参阅检查 Iceberg 元数据生成状态

检查 Iceberg 元数据生成状态

UniForm 将以下字段添加到 Unity Catalog 和 Iceberg 表元数据中,以跟踪元数据生成状态:

元数据字段 说明
converted_delta_version 已成功为其生成 Iceberg 元数据的最新版本 Delta 表。
converted_delta_timestamp 为其成功生成 Iceberg 元数据的最新 Delta 提交时间戳。

在 Azure Databricks 上,可通过执行一种操作来查看这些元数据字段:

  • 查看 DESCRIBE EXTENDED table_name 返回的 Delta Uniform Iceberg 部分。
  • 使用目录资源管理器查看表元数据。
  • 使用 REST API 获取表

有关如何在 Azure Databricks 之外查看表属性,请参阅 Iceberg 读取器客户端文档。 对于 OSS Apache Spark,可以使用以下语法查看这些属性:

SHOW TBLPROPERTIES <table-name>;

手动触发 Iceberg 元数据转换

可以手动触发最新版本 Delta 表的 Iceberg 元数据生成。 此操作同步运行,表示当它完成时,Iceberg 中可用的表内容反映了转换过程开始时可用的最新版本 Delta 表。

在正常情况下不需要进行此操作,但如果遇到以下情况,则会有所帮助:

  • 群集在自动生成元数据成功之前终止。
  • 错误或作业失败中断了元数据生成。
  • 不支持 UniForm Iceberg 元数据生成的客户端写入 Delta 表。

使用以下语法手动触发 Iceberg 元数据生成:

MSCK REPAIR TABLE <table-name> SYNC METADATA

请参阅 REPAIR TABLE

使用元数据 JSON 路径读取

一些 Iceberg 客户端要求提供版本控制元数据文件的路径,以注册外部 Iceberg 表。 每次 UniForm 将新版本 Delta 表转换为 Iceberg 时,它都会创建新的元数据 JSON 文件。

使用元数据 JSON 路径配置 Iceberg 的客户端包括 BigQuery。 有关配置详细信息,请参阅 Iceberg 读取器客户端文档。

Delta Lake 使用以下模式将 Iceberg 元数据存储在表目录下:

<table-path>/metadata/<version-number>-<uuid>.metadata.json

在 Azure Databricks 上,可通过执行一种操作来查看此元数据位置:

  • 查看 DESCRIBE EXTENDED table_name 返回的 Delta Uniform Iceberg 部分。
  • 使用目录资源管理器查看表元数据。
  • 将以下命令与 REST API 配合使用:
GET api/2.1/unity-catalog/tables/<catalog-name>.<schame-name>.<table-name>

响应包含以下信息:

{
    ...
          "delta_uniform_iceberg": {
              "metadata_location":  "<cloud-storage-uri>/metadata/v<version-number>-<uuid>.metadata.json"
    }
}

重要

基于路径的 Iceberg 读取器客户端可能需要手动更新和刷新元数据 JSON 路径来读取当前表版本。 用户在使用过期版本查询 Iceberg 表时可能会遇到错误,因为 Parquet 数据文件已使用 VACUUM 从 Delta 表中移除。

使用 Unity Catalog Iceberg 目录终结点读取

一些 Iceberg 客户端可以连接到 Iceberg REST 目录。 Unity Catalog 为 Delta 表(使用终结点 /api/2.1/unity-catalog/iceberg 启用了 UniForm)提供了 Iceberg REST 目录 API 的只读实现。 有关使用此 REST API 的详细信息,请参阅 Iceberg REST API 规范

已知支持 Iceberg 目录 API 的客户端包括 Apache Spark、Flink 和 Trino。 有关配置详细信息,请参阅 Iceberg 读取器客户端文档。

身份验证和授权

使用外部服务中的 api/2.1/unity-catalog/iceberg 终结点访问 Unity Catalog 中注册的数据有两个要求:

  • 使用 OAuth 或 Databricks 个人访问令牌进行身份验证。 请参阅对 Azure Databricks 资源的访问进行身份验证
  • 为元存储启用外部数据访问。 这会将访问限制为对从中读取 API的架构具有 EXTERNAL USE SCHEMA 特权的用户。

Apache Spark 配置示例

以下是配置 OSS Apache Spark 以将 UniForm 读取为 Iceberg 的设置示例:

"spark.sql.extensions": "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions",
"spark.sql.catalog.unity": "org.apache.iceberg.spark.SparkCatalog",
"spark.sql.catalog.unity.type": "rest",
"spark.sql.catalog.unity.uri": "<api-root>/api/2.1/unity-catalog/iceberg",
"spark.sql.catalog.unity.token": "<your_personal_access_token>",
"spark.sql.catalog.unity.warehouse": "<uc_catalog_name>"

将已生成个人访问令牌的工作区的完整 URL 替换为 <api-root>

使用 Spark 配置查询 Unity Catalog 中的表时,请记住以下几点:

  • 对象标识符使用模式 unity.<schema-name>.<table-name>

    此模式使用与 Unity Catalog 中所用相同的三层命名空间,但目录名称替换为 unity

  • 仅当运行特定于 Iceberg 的存储过程时,才需要 "spark.sql.extensions": "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions"

  • 如果使用云提供商进行存储,则必须将特定于该云的 Iceberg 捆绑包 jar 添加为 spark 包:

    • AWS:org.apache.iceberg:iceberg-aws-bundle:<iceberg-version>
    • Azure: org.apache.iceberg:iceberg-azure-bundle:<iceberg-version>
    • GCP:org.apache.iceberg:iceberg-gcp-bundle:<iceberg-version>

    有关详细信息,请参阅适用于 Spark 的 Iceberg AWS 集成文档

REST API curl 示例

还可以使用此 curl 示例中的 REST API 调用来加载表:

curl -X GET -H "Authentication: Bearer $OAUTH_TOKEN" -H "Accept: application/json" \
https://<workspace-instance>/api/2.1/unity-catalog/iceberg/v1/catalogs/<uc_catalog_name>/namespaces/<uc_schema_name>/tables/<uc_table_name>

然后你应该会收到类似于以下内容的响应:

{
  "metadata-location": "abfss://my-container@my-storage-account.dfs.core.chinacloudapi.cn/path/to/iceberg/table/metadata/file",
  "metadata": <iceberg-table-metadata-json>,
  "config": {
    "expires-at-ms": "<epoch-ts-in-millis>",
    "adls.sas-token.<storage-account-name>.dfs.core.chinacloudapi.cn": "<temporary-sas-token>"
  }
}

注意

响应中的 expires-at-ms 字段指示凭证的过期时间,默认的过期时间为 1 小时。 要获得更好的性能,请让客户端在过期时间到来前缓存凭证,然后再请求新凭证。

限制

所有 UniForm 表都存在以下限制:

  • UniForm 不适用于已启用删除向量的表。 请参阅什么是删除向量?
  • 已启用 UniForm 的 Dealta 表不支持 VOID 类型。
  • Iceberg 客户端只能从 UniForm 读取。 不支持写入。
  • 不管 UniForm 如何,Iceberg 读取器客户端可能都有各自局限性。 请参阅所选客户端文档。
  • 即使启用了 UniForm,Delta Sharing 的收件人也仅可将表读取为 Delta。
  • 某些 Delta Sharing 读取器客户端不支持 UniForm Iceberg 使用的一些 Delta Lake 表功能。 请参阅什么是 Delta Sharing?

启用 UniForm 时,更改数据馈送适用于 Delta 客户端,但在 Iceberg 中没有支持。