教程:创建第一个 Apache Iceberg™ 表

简介

本教程介绍如何创建 Apache Iceberg™ 表 使用 Snowflake 作为目录并支持读取和写入操作。Snowflake 的 Iceberg 表将常规 Snowflake 表的性能和查询语义与您管理的外部云存储结合在一起。

您可以使用 Snowsight 中的工作表或使用 Snowflake 客户端(如 SnowSQL)完成本教程。您可以复制并粘贴代码示例,然后运行它们。

您将学习以下内容

在本教程中,您将学习如何执行以下操作:

  • 创建并配置适用于 Snowflake 托管的 Iceberg 表的 外部卷。出于演示目的,本教程为 Amazon S3 创建了一个外部卷。

  • 创建两个使用 Snowflake 作为 Iceberg 目录的 Iceberg 表(Snowflake 托管的表)。

  • 将数据插入 Iceberg 表中。

  • 查询 Iceberg 表。

  • 从 Iceberg 表中删除行。

先决条件

在开始之前,您应该熟悉以下内容:

  • Snowflake 对象标识符 及其要求。

  • Snowflake 中的 Apache Iceberg 和 Iceberg 表。有关更多信息,请参阅 Apache Iceberg™ 表

  • 云对象存储。

  • 如果使用 S3,您应该熟悉 AWS Identity and Access Management (IAM) (https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) 和 IAM 策略元素 (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html)。

您需要:

  • 具有执行以下操作权限的角色的 Snowflake 用户:

    如果使用的是 30 天试用账户,则可使用为该账户创建的用户身份登录。该用户具有创建对象所需的权限的角色。

    如果没有具有必要权限的用户,则请让具有必要权限的用户为您创建一个。具有 ACCOUNTADMIN 角色的用户可以创建新用户并授予他们所需的权限。

  • 云存储提供商的管理员访问权限,以便配置外部卷。

  • 在托管 Snowflake 账户的同一区域中具有相同云提供商的存储桶(或容器)。

  • 访问账户中的 SNOWFLAKE_SAMPLE_DATA 数据库。默认情况下,Snowflake 会在新账户中创建示例数据库。如果您的账户中尚未创建数据库,请参阅 使用示例数据库

设置仓库和数据库

通过根据本教程创建仓库和数据库来设置您的环境。

CREATE WAREHOUSE iceberg_tutorial_wh
  WAREHOUSE_TYPE = STANDARD
  WAREHOUSE_SIZE = XSMALL;

USE WAREHOUSE iceberg_tutorial_wh;

CREATE OR REPLACE DATABASE iceberg_tutorial_db;
USE DATABASE iceberg_tutorial_db;
Copy

创建外部卷

在创建用于 Snowflake 的 Apache Iceberg™ 表之前,您必须具有外部卷。外部卷是一个账户级 Snowflake 对象,用于存储外部云存储的身份和访问管理 (IAM) 实体。

Snowflake 可使用外部卷安全地连接到您的云存储,以访问表数据和元数据。

出于演示目的,此步骤介绍了如何为 Amazon S3 创建外部卷。要为其他云存储服务创建外部卷,请参阅以下主题:

创建授予对 S3 位置的访问权限的 IAM 策略

要在 AWS 管理控制台中为 Snowflake 配置访问权限,请执行以下操作:

  1. 登录 AWS 管理控制台。

  2. 从主页仪表板搜索并选择 IAM

  3. 从左侧导航窗格中选择 Account settings

  4. Endpoints 列表中的 Security Token Service (STS) 下,找到账户所在位置对应的 Snowflake 区域。如果 STS status 处于非活动状态,请将切换键移动到 Active

  5. 从左侧导航窗格中选择 Policies

  6. 选择 Create Policy

    在 AWS 管理控制台中创建一个 IAM 策略。
  7. 对于 Policy editor,选择 JSON

  8. 添加策略,为 Snowflake 提供向 S3 位置读写数据所需的权限。

    以下示例策略授予对指定桶区中所有位置的访问权限。

    备注

    • 用实际桶名替换 my_bucket。您也可以在桶中指定路径;例如,my_bucket/path

    • "s3:prefix": 条件设置为 ["*"] 可授予对指定桶中所有前缀的访问权限;将其设置为 ["path/*"] 则可授予对桶中指定路径的访问权限。

    • 对于 政府区域 中的桶,桶 ARNs 使用 arn:aws-us-gov:s3::: 前缀。

    {
       "Version": "2012-10-17",
       "Statement": [
             {
                "Effect": "Allow",
                "Action": [
                   "s3:PutObject",
                   "s3:GetObject",
                   "s3:GetObjectVersion",
                   "s3:DeleteObject",
                   "s3:DeleteObjectVersion"
                ],
                "Resource": "arn:aws:s3:::<my_bucket>/*"
             },
             {
                "Effect": "Allow",
                "Action": [
                   "s3:ListBucket",
                   "s3:GetBucketLocation"
                ],
                "Resource": "arn:aws:s3:::<my_bucket>",
                "Condition": {
                   "StringLike": {
                         "s3:prefix": [
                            "*"
                         ]
                   }
                }
             }
       ]
    }
    
    Copy
  9. 选择 Next

  10. 输入 Policy name (例如 snowflake_access)和可选的 Description

  11. 选择 Create policy

创建 IAM 角色

创建一个可对包含数据文件的 S3 桶授予权限的 AWS IAM 角色。

  1. 在 Identity and Access Management (IAM) 控制面板的左侧导航窗格中,选择 Roles

  2. 选择 Create role

  3. 选择 AWS account 作为可信实体类型。

  4. An AWS account 下,选择 This account。在稍后的步骤中,您将修改信任关系,并授予对 Snowflake 的访问权限。

  5. 选择 Require external ID 选项。输入您选择的 外部 ID (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html)。例如 iceberg_table_external_id

    外部 ID 用于向第三方(如 Snowflake)授予对 AWS 资源(例如 S3 桶)的访问权限。

    创建一个具有外部 ID 的 IAM 角色。
  6. 选择 Next

  7. 选择您为外部卷创建的策略,然后选择 Next

  8. 输入角色的 Role name 和描述,然后选择 Create role

    您现在已经为一个 S3 位置创建了 IAM 策略,创建了一个 IAM 角色,并将策略附加到了该角色。

  9. 选择 View role 以查看角色摘要页面。找到并记录角色的 ARN (Amazon Resource Name) 值。

    带有链接的横幅,用于查看新的 IAM 角色。

在 Snowflake 中创建外部卷

使用 CREATE EXTERNAL VOLUME 命令创建外部卷。以下示例创建一个名为 iceberg_external_volume 的外部卷,其中定义了一个采用加密的 Amazon S3 存储位置。

CREATE OR REPLACE EXTERNAL VOLUME iceberg_external_volume
   STORAGE_LOCATIONS =
      (
         (
            NAME = 'my-s3-us-west-2'
            STORAGE_PROVIDER = 'S3'
            STORAGE_BASE_URL = 's3://<my_bucket>/'
            STORAGE_AWS_ROLE_ARN = '<arn:aws:iam::123456789012:role/myrole>'
            STORAGE_AWS_EXTERNAL_ID = 'iceberg_table_external_id'
         )
      );
Copy

该示例指定了与为外部卷创建的 IAM 角色关联的外部 ID (iceberg_table_external_id)。指定外部 ID 允许您跨多个外部卷使用相同的 IAM 角色(和外部 ID)。

备注

完全按照 AWS 提供的方式指定 ARNs。ARNs 区分大小写。

检索您的 Snowflake 账户的 AWS IAM 用户

  1. 使用 DESCRIBE EXTERNAL VOLUME 命令,检索自动为 Snowflake 账户创建的 AWS IAM 用户的 ARN。指定外部卷的名称。

    以下示例描述了名为 iceberg_external_volume 的外部卷:

    DESC EXTERNAL VOLUME iceberg_external_volume;
    
    Copy
  2. 记录 STORAGE_AWS_IAM_USER_ARN 属性的值,该属性是为 Snowflake 账户创建的 AWS IAM 用户;例如,arn:aws:iam::123456789001:user/abc1-b-self1234

    Snowflake 会为整个 Snowflake 账户配置单一 IAM 用户。账户中的所有 S3 外部卷均使用该 IAM 用户。

    备注

    如果创建外部卷时没有指定外部 ID (STORAGE_AWS_EXTERNAL_ID),Snowflake 会生成一个 ID 供您使用。记录该值,以便您可以使用生成的外部 ID 更新 IAM 角色信任策略。

授予访问桶对象的 IAM 用户权限

在此步骤中,您要配置权限,以允许 Snowflake 账户的 IAM 用户访问 S3 桶中的对象。

  1. 登录 AWS 管理控制台。

  2. 从主页仪表板搜索并选择 IAM

  3. 从左侧导航窗格中选择 Roles

  4. 选择为外部卷创建的 IAM 角色。

  5. 选择 Trust relationships 选项卡。

  6. 选择 Edit trust policy

  7. 使用记录的 DESC EXTERNAL VOLUME 输出值,修改策略文档。

    更新 IAM 角色的信任策略。

    IAM 角色的策略文档

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "",
          "Effect": "Allow",
          "Principal": {
            "AWS": "<snowflake_user_arn>"
          },
          "Action": "sts:AssumeRole",
          "Condition": {
            "StringEquals": {
              "sts:ExternalId": "<iceberg_table_external_id>"
            }
          }
        }
      ]
    }
    
    Copy

    其中:

    • snowflake_user_arn 是记录的 STORAGE_AWS_IAM_USER_ARN 值。

    • iceberg_table_external_id 是外部 ID。如果您在创建角色时 已经 指定了外部 ID,并使用相同的 ID 创建外部卷,请保持该值不变。否则,请使用记录的值更新 sts:ExternalId

    备注

    如果要新建外部卷(或使用 CREATE OR REPLACE EXTERNAL VOLUME 语法重新创建现有外部卷),则必须更新此策略文档,且不要提供您自己的外部 ID。出于安全原因,新的或重新创建的外部卷具有不同的外部 ID,除非您更新此信任策略,否则无法解析信任关系。

  8. 选择 Update policy 保存更改。

创建表

在此步骤中,您将创建两个 Apache Iceberg™ 表:一个具有标准 CREATE ICEBERG TABLE 语法,另一个具有 CREATE ICEBERG TABLE ...AS SELECT 变体。两个表都使用上一步中配置的外部卷。

您还将了解如何在数据库级别设置 Iceberg 目录和外部卷。

使用标准语法创建表

首先,使用标准 CREATE ICEBERG TABLE 语法创建 Iceberg 表。

指定 CATALOG = 'SNOWFLAKE',以便该表可使用 Snowflake 作为 Iceberg 目录。

要告知 Snowflake 在何处写入表数据和元数据何处,请为 BASE_LOCATION 参数指定值。该示例将表名称 (customer_iceberg) 设置为 BASE_LOCATION。这样,Snowflake 就会将数据和元数据写入与外部卷位置中的表同名的目录下。

CREATE OR REPLACE ICEBERG TABLE customer_iceberg (
    c_custkey INTEGER,
    c_name STRING,
    c_address STRING,
    c_nationkey INTEGER,
    c_phone STRING,
    c_acctbal INTEGER,
    c_mktsegment STRING,
    c_comment STRING
)
    CATALOG = 'SNOWFLAKE'
    EXTERNAL_VOLUME = 'iceberg_external_volume'
    BASE_LOCATION = 'customer_iceberg';
Copy

在本教程的后面部分,您将从 SNOWFLAKE_SAMPLE_DATA 数据库中的 snowflake_sample_data.tpch_sf1.customer 表中向此表加载数据。CREATE ICEBERG TABLE 语句中的列定义与示例表一致。

备注

如果您检查云存储位置,现在应该会在 BASE_LOCATION 下看到一个 Snowflake 在创建表时写入的名为 metadata/ 的目录。该目录存储表的元数据文件。

设置数据库的目录集成和外部卷

接下来,为您在本教程中创建的 iceberg_tutorial_db 设置 CATALOGEXTERNAL_VOLUME 参数。设置参数后,Snowflake 将对更改后创建的 所有 Iceberg 表使用您选择的特定目录和外部卷。

ALTER DATABASE iceberg_tutorial_db SET CATALOG = 'SNOWFLAKE';
ALTER DATABASE iceberg_tutorial_db SET EXTERNAL_VOLUME = 'iceberg_external_volume';
Copy

要进行验证,请检查当前数据库 (iceberg_tutorial_db):

SHOW PARAMETERS IN DATABASE ;
Copy

使用 CTAS 创建表

最后,使用 CREATE ICEBERG TABLE ...AS SELECT 语法创建名为 nation_iceberg 的第二个 Iceberg 表。我们将以 Snowflake 示例数据库中的 snowflake_sample_data.tpch_sf1.nation 表为基础创建新表。

备注

由于只需为数据库设置 CATALOGEXTERNAL_VOLUME 参数,因此可以省略 CREATE ICEBERG TABLE 语句中的两个参数。nation_iceberg 表将会从数据库中继承值。

CREATE OR REPLACE ICEBERG TABLE nation_iceberg (
  n_nationkey INTEGER,
  n_name STRING
)
  BASE_LOCATION = 'nation_iceberg'
  AS SELECT
    N_NATIONKEY,
    N_NAME
  FROM snowflake_sample_data.tpch_sf1.nation;
Copy

加载数据并查询表

在此步骤中,首先使用 INSERT INTO <table> 将数据从 Snowflake 示例数据库加载到 customer_iceberg 表中:

INSERT INTO customer_iceberg
  SELECT * FROM snowflake_sample_data.tpch_sf1.customer;
Copy

备注

如果检查云存储位置,现在应该会在以下路径中看到一个包含表数据文件的目录:STORAGE_BASE_URL/BASE_LOCATION/customer_iceberg/data/

现在表中存在数据,因此您可以查询该表。以下查询将 customer_iceberg 表与 nation_iceberg 表(已包含数据)联结起来。

SELECT
    c.c_name AS customer_name,
    c.c_mktsegment AS market_segment,
    n.n_name AS nation
  FROM customer_iceberg c
  INNER JOIN nation_iceberg n
    ON c.c_nationkey = n.n_nationkey
  LIMIT 15;
Copy

输出:

+--------------------+----------------+----------------+
| CUSTOMER_NAME      | MARKET_SEGMENT | NATION         |
|--------------------+----------------+----------------|
| Customer#000015001 | HOUSEHOLD      | MOROCCO        |
| Customer#000015002 | BUILDING       | VIETNAM        |
| Customer#000015003 | BUILDING       | INDONESIA      |
| Customer#000015004 | FURNITURE      | SAUDI ARABIA   |
| Customer#000015005 | HOUSEHOLD      | KENYA          |
| Customer#000015006 | BUILDING       | UNITED KINGDOM |
| Customer#000015007 | MACHINERY      | FRANCE         |
| Customer#000015008 | HOUSEHOLD      | INDIA          |
| Customer#000015009 | FURNITURE      | EGYPT          |
| Customer#000015010 | HOUSEHOLD      | ETHIOPIA       |
| Customer#000015011 | FURNITURE      | UNITED KINGDOM |
| Customer#000015012 | BUILDING       | FRANCE         |
| Customer#000015013 | FURNITURE      | SAUDI ARABIA   |
| Customer#000015014 | HOUSEHOLD      | KENYA          |
| Customer#000015015 | MACHINERY      | ROMANIA        |
+--------------------+----------------+----------------+

删除行

在此步骤中,您将使用 DELETE 语句从 customer_iceberg 表中移除特定行。

首先查询表的前 10 行,请注意,其中 4 行属于 AUTOMOBILE 细分市场:

SELECT
    c_name AS customer_name,
    c_mktsegment AS market_segment
  FROM customer_iceberg
  LIMIT 10;
Copy

输出:

+--------------------+----------------+
| CUSTOMER_NAME      | MARKET_SEGMENT |
|--------------------+----------------|
| Customer#000000001 | BUILDING       |
| Customer#000000002 | AUTOMOBILE     |
| Customer#000000003 | AUTOMOBILE     |
| Customer#000000004 | MACHINERY      |
| Customer#000000005 | HOUSEHOLD      |
| Customer#000000006 | AUTOMOBILE     |
| Customer#000000007 | AUTOMOBILE     |
| Customer#000000008 | BUILDING       |
| Customer#000000009 | FURNITURE      |
| Customer#000000010 | HOUSEHOLD      |
+--------------------+----------------+

接下来,我们将使用 DELETE 语句从细分市场为 AUTOMOBILE 的表中删除所有行:

DELETE FROM customer_iceberg WHERE c_mktsegment = 'AUTOMOBILE';
Copy

输出:

+------------------------+
| number of rows deleted |
|------------------------|
|                  29752 |
+------------------------+

最后,您可以仔细检查行是否已消失:

SELECT
    c_name AS customer_name,
    c_mktsegment AS market_segment
 FROM customer_iceberg
 WHERE c_mktsegment = 'AUTOMOBILE';
Copy

输出:

+---------------+----------------+
| CUSTOMER_NAME | MARKET_SEGMENT |
|---------------+----------------|
+---------------+----------------+
0 Row(s) produced. Time Elapsed: 1.426s

恭喜!

您刚刚写入、读取和修改了第一个 Snowflake 托管的 Iceberg 表。您还学习了如何为 Iceberg 表存储配置外部卷,以及如何为数据库中的所有 Iceberg 表设置 Iceberg 目录和外部卷。

清理

要删除根据本教程创建的所有对象,请运行 DROP 语句。

替换以下值:

  • my_other_database 替换为要使用的数据库的名称,以便您可以删除为本教程创建的数据库。

  • my_other_warehouse 替换为创建的外部卷的名称。

DROP ICEBERG TABLE customer_iceberg;
DROP ICEBERG TABLE nation_iceberg;
DROP EXTERNAL VOLUME iceberg_external_volume;
USE DATABASE <my_other_database>;
DROP DATABASE iceberg_tutorial_db;
USE WAREHOUSE <my_other_warehouse>;
DROP WAREHOUSE iceberg_tutorial_wh;
Copy

总结和其他资源

在本教程中,您遵循了创建和使用 Snowflake 管理的 Apache Iceberg™ 表的端到端工作流程。

在此过程中,您完成了以下任务:

要了解有关 Snowflake 的 Iceberg 表的更多信息,请参阅 Iceberg 表文档。有关其他 Iceberg 教程和快速入门,请参阅 Snowflake 教程 页面。

语言: 中文