对外部托管的 Apache Iceberg™ 表的写入支持

对外部托管的 Apache Iceberg™ 表 的写入支持,可让您对由外部 Iceberg REST 目录管理的表执行写入操作。Snowflake 中的 Iceberg 表链接到远程目录中的表。当您对 Snowflake 中的表进行更改时,Snowflake 会将相同的更改提交到您的远程目录。

此预览功能扩展了 Snowflake 与第三方系统之间的互操作性,即使您使用外部 Iceberg 目录,也可以使用 Snowflake 处理数据工程工作负载。

主要用例包括:

  • 使用 Iceberg 表构建复杂的数据工程管道:通过 Snowflake 向外部目录中的 Iceberg 表写入数据,您可以使用 Snowpark 或 Snowflake SQL 构建复杂的数据管道,用于引入、转换和处理 Iceberg 表数据。您可以使用 Snowflake 或其他引擎查询数据。同样,您可以使用 Snowflake 合作伙伴工具 来构建 Iceberg 数据工程管道。

  • 将您的数据提供给 Iceberg 生态系统:通过写入外部目录中的 Iceberg 表,您可以将数据提供给 Iceberg 生态系统。您可以查询 Snowflake 中已经存在的数据并将其写入 Iceberg 表中。为了使您的 Iceberg 表与 Snowflake 表保持同步,您可以使用诸如 INSERT INTO ... SELECT FROM 之类的操作来执行以下操作:

    • 将现有数据从标准 Snowflake 表复制到 Iceberg 表中。

    • 使用 Snowflake 流插入数据。

注意事项

对外部托管的 Iceberg 表使用写入支持时,请考虑以下事项:

  • Snowflake 为外部托管的表提供数据定义语言 (DDL) 和数据操作语言 (DML) 命令。但是,您可以使用外部目录和外部存储提供商提供的工具来配置元数据和数据保留。有关更多信息,请参阅 使用外部目录的表

    对于写入,Snowflake 确保在更新 Snowflake 中的表之前将更改提交到您的远程目录。

  • 如果您使用目录链接的数据库,则可以使用带列定义的 CREATE ICEBERG TABLE 语法在 Snowflake 远程目录中创建表。如果您使用标准的 Snowflake 数据库(未链接到目录),则必须先在远程目录中创建表。之后,您可以使用 CREATE ICEBERG TABLE(Iceberg REST 目录) 语法在 Snowflake 中创建一个 Iceberg 表并将数据写入该表。

  • 对于 AWS Glue Data Catalog:通过 Snowflake 删除外部托管的表不会删除基础表文件。此行为特定于 AWS Glue Data Catalog 的实现。

  • 如果您曾参与此功能的非公开预览,则您账户中的定位行级删除功能可能已默认启用。要进行检查,请运行以下命令:

    SHOW PARAMETERS LIKE 'ENABLE_ICEBERG_MERGE_ON_READ' IN ACCOUNT;
    
    Copy

    如果该参数在您的账户中可见(无论其值如何),则会启用位置删除功能。要关闭位置删除,请在表、架构或数据库级别将 ENABLE_ICEBERG_MERGE_ON_READ 参数设置为 FALSE。

  • 不支持对包含以下 Iceberg 数据类型的外部托管表进行写入操作:

    • uuid

    • fixed(L)

  • 在使用 Snowflake 写入外部托管的 Iceberg 表时,以下功能暂不支持:

    • 目录分发的凭据。

    • GCS 或 Azure 外部卷的服务器端加密 (SSE)。

    • 多语句事务Snowflake 仅支持自动提交事务。

    • 转换为 Snowflake 托管的表。

    • 不符合 Iceberg REST 协议的外部 Iceberg 目录。

    • 行级删除(读取时合并)。

    • 创建表时使用 OR REPLACE 选项。

    • 如果使用 AWS Glue 作为远程目录,应使用 CREATE TABLE ... AS SELECT 语法。

  • 要在目录链接数据库中创建架构,请注意以下事项:

    • 仅当您使用目录链接的数据库时,CREATE SCHEMA 命令才会在远程目录中创建相应的命名空间。

    • 不支持 ALTER 和 CLONE 选项。

    • 架构名称不支持分隔符。仅支持字母数字架构名称。

工作流程

使用本不分中的工作流程开始使用此功能:

  1. 配置外部卷

  2. 创建目录集成

  3. 从以下选项中选择:

    • 创建目录链接数据库。通过此选项,您可以向目录中自动发现的 Iceberg 表写入数据,或使用目录链接的数据库创建更多 Iceberg 表。

    • :ref:`创建 Iceberg 表 <label-tables_iceberg_external_writes_create_table>`(在目录链接数据库或标准 Snowflake 数据库中)。使用此选项,必须先在远程目录中创建表,然后才能在 Snowflake 中创建外部托管的 Iceberg 表。

完成这些步骤后,您可以对 Iceberg 表执行 写入操作

配置外部卷以写入到外部托管的表

要启用对外部托管表的写入功能,必须使用为 Snowflake 服务主体配置了读写权限的外部卷(该权限要求与 Snowflake 托管表所需的权限相同)。

请指定您的 Iceberg REST 目录用于写入 Iceberg 数据和元数据的存储位置 (STORAGE_BASE_URL)。

例如,以下语句可为 S3 创建一个启用加密的外部卷,该卷允许对名为 my-iceberg-tables 的存储桶进行写入访问:

CREATE OR REPLACE EXTERNAL VOLUME my_external_volume
  STORAGE_LOCATIONS =
    (
      (
        NAME = 'my-s3-us-west-2'
        STORAGE_PROVIDER = 'S3'
        STORAGE_BASE_URL = 's3://my-iceberg-tables/'
        STORAGE_AWS_ROLE_ARN = 'arn:aws:iam::123456789012:role/my-write-access-role'
        ENCRYPTION = ( TYPE = 'AWS_SSE_S3' )
      )
    )
  ALLOW_WRITES = TRUE;
Copy

备注

必须使用读写权限配置外部卷,并将 ALLOW_WRITES 参数设置为 TRUE

有关完整说明,请参阅以下主题:

有关所需权限的更多信息,请参阅 授予 Snowflake 对存储的访问权限

配置目录集成

要写入外部托管的 Iceberg 表,必须配置目录集成以将 Snowflake 连接到远程目录。

您的远程目录必须符合开源 Apache Iceberg REST OpenAPI 规范 (https://github.com/apache/iceberg/blob/main/open-api/rest-catalog-open-api.yaml),例如 Open Catalog 或 AWS Glue Iceberg REST 目录 (https://docs.aws.amazon.com/glue/latest/dg/connect-glu-iceberg-rest.html)。

要创建目录集成,请参阅以下主题中的说明:

创建目录链接数据库

Snowflake 支持在目录链接数据库中创建可写的外部托管表,该数据库是与外部 Iceberg REST 目录同步的 Snowflake 数据库。您也可以向 Snowflake 在远程目录中自动发现的 Iceberg 表写入数据。有关更多信息,请参阅 为 Apache Iceberg™ 表使用目录链接的数据库

备注

或者,您可以在 标准 Snowflake 数据库 中创建可写入的外部托管 Iceberg 表。

以下示例使用 CREATE DATABASE(目录链接) 命令创建使用外部卷的目录链接数据库:

CREATE DATABASE my_catalog_linked_db
  LINKED_CATALOG = (
    CATALOG = 'glue_rest_catalog_int'
  ),
  EXTERNAL_VOLUME = 'my_external_vol';
Copy

使用 CREATE SCHEMA 在外部目录中创建命名空间

要创建用于在外部目录中组织 Iceberg 表的命名空间,可以在目录链接数据库中使用 CREATE SCHEMA 命令。该命令在您链接的 Iceberg REST 目录中创建命名空间,并在 Snowflake 数据库中创建相应的架构。

CREATE SCHEMA 'my_namespace';
Copy

备注

架构名称必须是字母数字,并且不能包含分隔符。

DROP SCHEMA

您也可以使用 DROP SCHEMA 命令同时从目录链接数据库中删除架构,并从远程目录中删除相应的命名空间。

DROP SCHEMA 'my_namespace';
Copy

创建 Iceberg 表

创建可从 Snowflake 写入的外部托管 Iceberg 表的具体操作会因您使用的数据库类型而异:

在目录链接的数据库中创建 Iceberg 表

要同时在 Snowflake 和外部目录中创建表,请使用 CREATE ICEBERG TABLE(目录链接的数据库) 命令。

以下示例使用之前为 AWS Glue REST 创建的外部卷和目录集成来创建可写入的 Iceberg 表。

USE DATABASE my_catalog_linked_db;

USE SCHEMA my_namespace;

CREATE OR REPLACE ICEBERG TABLE my_iceberg_table (
  first_name string,
  last_name string,
  amount int,
  create_date date
);
Copy

运行该命令时,Snowflake 会在您的远程目录中创建一个新的 Iceberg 表,并在 Snowflake 中创建一个链接的、可写的外部托管表。

在标准 Snowflake 数据库中创建 Iceberg 表

如果使用标准 Snowflake 数据库,则必须先在远程目录中创建表。例如,您可以使用 Spark 将一个 Iceberg 表写入 Open Catalog。

在远程目录中创建表后,使用 CREATE ICEBERG TABLE(Iceberg REST 目录) 命令在 Snowflake 中创建 Iceberg 表对象。对于 CATALOG_TABLE_NAME,指定表在远程目录中显示的名称。

例如:

CREATE OR REPLACE ICEBERG TABLE my_iceberg_table
  EXTERNAL_VOLUME = 'my_external_volume'
  CATALOG = 'my_rest_catalog_integration'
  CATALOG_TABLE_NAME = 'my_remote_table_name';
Copy

运行该命令时,Snowflake 会在 Snowflake 中创建一个可写入的外部托管表,该表链接到远程目录中的现有表。

删除 Iceberg 表

您可以使用 DROP ICEBERG TABLE 命令同时从 Snowflake 和远程目录中删除外部托管的可写入的 Iceberg 表。

DROP ICEBERG TABLE my_iceberg_table;
Copy

Snowflake 会删除该表,同时调用您的远程 Iceberg 目录,指示其删除该表并清除表的底层数据和元数据。

只有在确认表已成功从远程目录中删除后,Snowflake 才会删除该表。

备注

如果您使用 AWS Glue 数据目录作为外部目录,则通过 Snowflake 删除外部管理的表不会删除基础表文件。此行为特定于 AWS Glue Data Catalog 的实现。

写入外部托管的 Iceberg 表

您可以对外部托管的 Iceberg 表使用以下 DML 命令:

您也可以使用 Snowpark API 来处理 Iceberg 表。

示例

您可以使用以下基本示例开始写入 Iceberg 表。

INSERT

使用 INSERT 将值插入到 Iceberg 表中:

INSERT INTO my_iceberg_table VALUES (1, 'a');
INSERT INTO my_iceberg_table VALUES (2, 'b');
INSERT INTO my_iceberg_table VALUES (3, 'c');
Copy

UPDATE

使用 UPDATE 更新 Iceberg 表中的值:

UPDATE my_iceberg_table
  SET a = 10
  WHERE b = 'b';
Copy

DELETE

使用 DELETE 从 Iceberg 表中删除值:

DELETE my_iceberg_table
  WHERE b = 'a';
Copy

MERGE

在 Iceberg 表中使用 MERGE

MERGE INTO my_iceberg_table USING my_snowflake_table
  ON my_iceberg_table.a = my_snowflake_table.a
  WHEN MATCHED THEN
      UPDATE SET my_iceberg_table.b = my_snowflake_table.b
  WHEN NOT MATCHED THEN
      INSERT VALUES (my_snowflake_table.a, my_snowflake_table.b);
Copy

COPY INTO <table>

使用 COPY INTO <table> 将数据加载到 Iceberg 表中。

COPY INTO customer_iceberg_ingest
  FROM @my_parquet_stage
  FILE_FORMAT = 'my_parquet_format'
  LOAD_MODE = ADD_FILES_COPY
  PURGE = TRUE
  MATCH_BY_COLUMN_NAME = CASE_SENSITIVE;
Copy

有关更多信息,请参阅 将数据加载到 Apache Iceberg™ 表中 以获取更多信息。

使用流更改数据捕获

表流 跟踪对变更数据捕获 (CDC) 的源表中的行所做的更改。源表可以是标准的 Snowflake 表、Snowflake 管理的 Iceberg 表或外部管理的 Iceberg 表。您可以使用 INSERT INTO ... SELECT FROM 命令将更改插入到外部管理的 Iceberg 表中。

备注

如果您的源表是外部管理的 Iceberg 表,则在创建流时必须使用 INSERT_ONLY = TRUE。

CREATE OR REPLACE STREAM my_stream ON TABLE my_snowflake_table;

//...

INSERT INTO my_iceberg_table(id,name)
  SELECT id, name
  FROM my_stream;
Copy

使用 Snowpark

创建一个函数,使用 Snowpark Python 将数据从 Snowflake 表中复制到 Iceberg 表。

def copy_into_iceberg():

  try:
      df = session.table("my_snowflake_table")

      df.write.save_as_table("my_iceberg_table")

  except Exception as e:
      print(f"Error processing {table_name}: {e}")
Copy

故障排除

如果 Snowflake 尝试向外部目录提交表更改时出现问题,Snowflake 会返回以下错误消息之一。

错误

004185=SQL Execution Error: Failed while committing transaction to external catalog. Error:''{0}''

或者:

004185=SQL Execution Error: Failed while committing transaction to external catalog with unresolvable commit conflicts. Error:''{0}''

原因

提交到外部目录失败,其中 {0} 是外部目录返回的异常(如果可用);否则,Snowflake 会将 Exception unavailable 报告为失败原因。如果 Snowflake 在尝试将事务提交到外部目录时遇到无法解决的提交冲突,错误消息将包含 with unresolvable commit conflicts

错误

004500=SQL Execution Error: Cannot verify the status of transaction from external catalog. The statement ''{0}'' with transaction id {1} may or may not have committed to external catalog. Error:''{2}''

原因

对外部目录的提交导致外部目录没有响应。该消息包含外部目录返回的异常(如果可用);否则,Snowflake 会将 Exception unavailable 报告为失败原因。

语言: 中文