View a markdown version of this page

在 Amazon Redshift 中引用 Iceberg 表 - Amazon Redshift

从补丁 198 开始,Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息,请参阅博客文章

在 Amazon Redshift 中引用 Iceberg 表

Amazon Redshift 提供了多种方法来引用存储在数据湖中的 Apache Iceberg 表。您可以使用外部架构来创建对包含 Iceberg 表的 Data Catalog 数据库的引用,也可以使用三部分表示法直接访问自动挂载的目录。

使用外部架构引用 Iceberg 表

外部架构提供了在 Amazon Redshift 中引用 Data Catalog 中的表的方法。创建外部架构时,您在 Amazon Redshift 数据库与包含您 Iceberg 表的特定 Data Catalog 数据库之间建立了连接。

要为 Iceberg 表创建外部架构,请执行以下操作:

CREATE EXTERNAL SCHEMA schema_name FROM DATA CATALOG DATABASE 'glue_database_name' IAM_ROLE 'arn:aws:iam::account-id:role/role-name';

创建外部架构后,您可以使用两部分表示法查询 Iceberg 表:

SELECT * FROM schema_name.iceberg_table_name;

您也可以将 Iceberg 表与本地 Amazon Redshift 表联接起来:

SELECT r.customer_id, i.order_date, r.customer_name FROM local_customers r JOIN schema_name.iceberg_orders i ON r.customer_id = i.customer_id;

对自动挂载的目录使用三部分表示法

您可以使用三部分表示法,直接引用自动挂载的目录中的表而无需创建外部架构。在处理与 AWS Lake Formation 联合的 Amazon S3 表存储桶时,此方法尤为有用。有关设置 Data Catalog 自动挂载的信息,请参阅 Simplify external object access in Amazon Redshift using automatic mounting of the AWS Glue Data Catalog

三部分表示法如下所示:

"catalog_name".database_name.table_name

例如,要在自动挂载的 Amazon S3 表目录中查询 Iceberg 表,请执行以下操作:

SELECT * FROM "my_table_bucket@s3tablescatalog".my_database.my_iceberg_table;

有关将 Amazon S3 表存储桶与 Amazon Redshift 集成的更多信息,请参阅《Amazon S3 用户指南》中的将 S3 表类数据存储服务与 Amazon Redshift 集成

您还可以引用位于自动挂载的根目录 awsdatacatalog 下的表,该目录提供对在 AWS Glue Data Catalog 中注册的数据库和表的直接访问:

SELECT * FROM awsdatacatalog.my_database.my_iceberg_table;

有关使用 awsdatacatalog 根目录的更多信息,请参阅《Amazon Redshift 管理指南》中的查询 AWS Glue Data Catalog 和《AWS Lake Formation 开发人员指南》中的管理 Data Catalog 命名空间

也可以使用 USE 语句来为 Amazon S3 表存储桶设置默认的目录和数据库:

USE "my_table_bucket@s3tablescatalog".my_database; SELECT * FROM my_iceberg_table;

要使用 Amazon S3 表存储桶设置架构解析的搜索路径,请执行以下操作:

USE "my_table_bucket@s3tablescatalog"; SET search_path TO my_database; SELECT * FROM my_iceberg_table;
注意

s3tablescatalog 仅支持 USE 语句和 search_path。它们不能与 awsdatacatalog 结合使用。要引用 awsdatacatalog 中的表,请使用完整的三部分表示法。

引用 Iceberg 表的最佳实践

Apache Iceberg 表是由多个文件组成的单个逻辑实体:根元数据文件(metadata.json)、清单列表、清单文件和数据文件(通常为 .parquet)。根元数据文件充当入口点,并包含对构成该表的所有其它文件的引用。当您向 Amazon Redshift 授予对 Iceberg 表的访问权限时,Amazon Redshift 使用根元数据文件来发现和读取所有引用的数据文件。如果 Amazon Redshift 有权访问根元数据文件,则它也会取得并需要访问所有基础数据文件的权限。这与 Iceberg 的设计一致,其中,表级访问是预期的授权单位。

为了提高查询性能,Amazon Redshift 将 Iceberg 元数据文件(包括根元数据文件、清单列表和清单文件)缓存在内存中。根元数据文件(metadata.json)将以可配置的间隔(TTL)针对 Amazon S3 进行重新验证。TTL 到期后,Amazon Redshift 对根元数据文件执行 Amazon S3 HEAD 请求,以验证 IAM 角色是否仍具有访问权限以及该文件是否未被修改。如果权限检查失败或文件已更改,则会逐出缓存的条目并从 Amazon S3 重新提取元数据。由于根元数据文件是所有表访问的入口点,因此,此重新验证可用作整个表的权限门。清单列表和清单文件是在不进行独立的 TTL 重新验证的情况下缓存的,它们的访问有效性源自根元数据权限检查。这意味着,如果您撤销 Amazon S3 对 Iceberg 表的权限,则在使用缓存的元数据时,查询最多可以继续成功进行 2 分钟。

重要

Amazon S3 支持您在各个对象级别设置权限,这意味着在技术上可以授予对 Iceberg 表的元数据的访问权限,同时限制访问其某些底层数据文件。这会造成权限不一致,从而可能导致 Amazon Redshift 中的查询失败或意外访问错误。

Amazon Redshift 会定期验证对缓存的根元数据文件的访问权限,但不会在 Amazon S3 存储桶中的元数据级别权限与数据文件级别权限之间验证或强制实施一致性。客户有责任确保在构成 Iceberg 表的所有文件间一致地应用权限。

为避免这种情况,当在 Amazon Redshift 中引用 Iceberg 表时,请考虑以下最佳实践:

  • 使用描述性架构名称:创建外部架构时,请使用能清楚表明数据来源和用途的名称,例如 sales_data_lakecustomer_analytics

  • 利用表统计数据:确保使用 AWS Glue 为 Iceberg 表生成列统计数据,用来优化查询性能。Amazon Redshift 使用这些统计数据进行查询规划和优化。

  • 考虑数据新鲜度:在您查询 Iceberg 表时,其他服务可能会更新这些表。Amazon Redshift 提供事务一致性,可确保您在执行查询期间看到一致的数据快照。

  • 使用适当的 IAM 权限:确保您的 Amazon Redshift 集群或工作组具有必要的 IAM 权限,可以访问存储 Iceberg 表的 Amazon S3 位置以及 Data Catalog 元数据。

  • 表级别权限:在表级别授予权限,而不是在单个文件级别授予权限。

  • 统一权限:确保在整个 Amazon S3 路径上统一访问您的 Iceberg 表,包括所有元数据、清单和数据文件。

  • 避免限制性对象级别策略:不要对 Iceberg 表的前缀内的各个 Parquet 文件设置限制性对象级别策略。

  • 了解权限变更的缓存 TTL:当您撤销 Amazon S3 对 Iceberg 表的权限时,使用缓存的根元数据查询可能会继续成功,直至配置的 TTL 持续时间(默认值:2 分钟)。

  • 监控查询性能:使用 Amazon Redshift 查询监控功能,跟踪对 Iceberg 表进行查询的性能并根据需要进行优化。

常见引用模式

以下示例演示引用 Iceberg 表的常用模式:

跨多个 Iceberg 表聚合数据:

SELECT region, SUM(sales_amount) as total_sales, COUNT(*) as transaction_count FROM data_lake.sales_transactions WHERE transaction_date >= '2024-01-01' GROUP BY region ORDER BY total_sales DESC;

将 Iceberg 表与本地 Amazon Redshift 表联接:

SELECT c.customer_name, c.customer_tier, SUM(o.order_amount) as total_orders FROM customers c JOIN data_lake.order_history o ON c.customer_id = o.customer_id WHERE o.order_date >= CURRENT_DATE - INTERVAL '30 days' GROUP BY c.customer_name, c.customer_tier;

在复杂查询中使用三部分表示法:

WITH recent_orders AS ( SELECT customer_id, order_date, order_amount FROM "analytics_bucket@s3tablescatalog".ecommerce.orders WHERE order_date >= CURRENT_DATE - INTERVAL '7 days' ) SELECT customer_id, COUNT(*) as order_count, AVG(order_amount) as avg_order_value FROM recent_orders GROUP BY customer_id HAVING COUNT(*) > 1;