View a markdown version of this page

SQL 命令 - Amazon Redshift

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

SQL 命令

Amazon Redshift 中的 Apache Iceberg 表提供了一种强大的方法用于管理数据湖中的大型分析数据集。这些表支持 ACID 事务、架构发展和时间旅行功能,同时保持了高性能的分析工作负载。使用 Apache Iceberg 表,您可以高效地组织和分区数据,控制文件格式和文件压缩,并与其他 AWS 服务无缝集成。

您可以使用 CREATE TABLE ... USING ICEBERGCREATE TABLE ... USING ICEBERG AS SELECT 命令创建分区和未分区的 Iceberg 表。您可以使用外部架构表示法 (external_schema.table_name) 或三部分表示法 ("catalog_name".database_name.table_name) 引用 Iceberg 表。本部分中的示例将演示这两种方法。

创建表之后,您可以使用标准 INSERT 命令添加数据。请记住,虽然 Amazon Redshift 可处理许多 Iceberg 数据类型,但在插入信息时,您可能需要转换某些数据格式。

您可以使用 SHOW TABLES 命令查看 Iceberg 表。如果要从 AWS Glue Data Catalog 中移除表,您可以使用 DROP TABLE 命令。请注意,这只会移除表注册信息。实际数据仍保留在存储中,直到您单独将其删除。

您也可以使用 DELETEUPDATEMERGE 命令修改现有数据。Iceberg 表目前尚不支持所有其他 SQL 语句,例如 ALTER TABLE

您可以对并非由 Amazon Redshift 创建的 Iceberg 表执行写入操作。但是,这里有一些限制:

  • 该表必须是 Iceberg v2 表。

  • 该表必须使用 Parquet 作为默认数据格式。

  • 该表不可将元数据压缩设置为 True。

  • 该表不可启用写入-审计-发布(WAP)。

以下部分演示了在 Amazon Redshift 中创建、插入、修改和管理 Iceberg 表的 SQL 语法。

CREATE TABLE

CREATE TABLE [IF NOT EXISTS] <external_schema>.<table_name> ( column_name data_type [, ...] ) USING ICEBERG [LOCATION 's3://your-bucket-name/prefix/'] [PARTITIONED BY [[column_name | transform_function]], ...] [TABLE PROPERTIES ('compression_type'='<compression_value>')]

对于 S3 表存储桶,您也可以使用三部分表示法。

CREATE TABLE "<table_bucket_name>@s3tablescatalog".<database_name>.<table_name> ( column_name data_type [, ...] ) USING ICEBERG [PARTITIONED BY [[column_name | transform_function]], ...] [TABLE PROPERTIES ('compression_type'='<compression_value>')]

请注意,<external_schema> 必须是创建外部表时使用的现有外部架构名称。有关如何创建和管理外部架构的更多信息,请参阅 Amazon Redshift 文档中的 CREATE EXTERNAL SCHEMA

LOCATION 子句定义此新创建的 Iceberg 表的表位置。对于 Amazon S3 表,无法指定 LOCATION,因为表的位置由 Amazon S3 表目录 (s3tablescatalog) 确定。

在所有其他情况下,LOCATION 均必填,并且应为空位置,也就是说没有现有的 Amazon S3 对象共享了这个相同的存储桶和前缀。请注意,Amazon S3 存储桶必须与 Amazon Redshift 集群位于同一区域。

但是,AWS 提供了一种方法,用于将存储在一个 AWS 区域的 AWS Glue Data Catalog 中的 Iceberg 表的数据复制到不同 AWS 区域,这样您就可以将写入操作复制到不同的区域。有关更多信息,请参阅跨 AWS 区域复制数据

PARTITIONED BY 定义 Iceberg 表分区。Amazon Redshift 支持所有 Iceberg v2 分区转换,但 void 除外。以下是当前支持的转换列表:

  • 身份

  • bucket[N]

  • truncate[W]

  • 个月

  • day

  • 小时

有关这些转换的完整定义以及兼容的数据类型,请参阅 Apache Iceberg 文档中的 Partition Transforms

PARTITIONED BY 支持多个级别的分区。例如,您可以运行以下命令:

CREATE TABLE ... USING ICEBERG LOCATION ... PARTITIONED BY (bucket(16, id), year(ship_date));

但是,Amazon Redshift 不支持在多个转换中使用单列。例如,不支持以下语法。

CREATE TABLE ... USING ICEBERG LOCATION ... PARTITIONED BY (bucket(16, ship_date), year(ship_date));

TABLE PROPERTIES 子句定义此 Iceberg 表的额外表属性。唯一支持的表属性是 compression_type,该属性定义默认的 Parquet 数据文件压缩。如果未指定该项,则使用 snappy 作为压缩编解码器。compression_type 的可能值包括 zstdbrotligzipsnappyuncompressed

注意

Iceberg 表不支持 CREATE TABLE ... LIKE ...。此外,Iceberg 表不支持列约束和列属性,这与 RMS 表不同。

或者,您可以使用 CREATE TABLE AS SELECT 在单个操作中创建和填充 Iceberg 表:

CREATE TABLE AS SELECT

CREATE TABLE <external_schema>.<table_name> [( column_name[, ...] )] USING ICEBERG [LOCATION 's3://your-bucket-name/prefix/'] [PARTITIONED BY [[column_name | transform_function]], ...] [TABLE PROPERTIES ('compression_type'='<compression-value>')] AS SELECT query

您也可以使用三部分表示法在自动挂载目录中创建表:

CREATE TABLE "<catalog_name>".<database_name>.<table_name> [( column_name[, ...] )] USING ICEBERG [LOCATION 's3://your-bucket-name/prefix/'] [PARTITIONED BY [[column_name | transform_function]], ...] [TABLE PROPERTIES ('compression_type'='<compression-value>')] AS SELECT query

这与 CREATE TABLE 语句类似,不同之处在于 CREATE 后跟 SELECT 语句,用于在表中填充 SELECT 查询结果。

此处的 CREATE TABLE 子句不再允许您指定数据类型,因为列的数据类型将由 SELECT 查询决定。

如果 SELECT 查询因任何原因失败,则此查询将失败,并且不会创建 Iceberg 表。

您可以使用 SHOW TABLE 查看 Iceberg 表的结构:

SHOW TABLE

SHOW TABLE <external_schema>.<table_name>

您还可以对自动挂载目录使用三部分表示法:

SHOW TABLE "<catalog_name>".<database_name>.<table_name>

SHOW TABLE 显示 Iceberg 表的 CREATE TABLE 语句。该命令将根据表的类型显示相应的结果。以下是 Iceberg 表的 SHOW TABLE 输出示例:

CREATE TABLE my_schema.items (id int, price decimal(5, 2)) USING ICEBERG LOCATION 's3://my_s3_bucket/items/' PARTITIONED BY (bucket(16, id)) TABLE PROPERTIES ('compression_type'='snappy')
注意

对于 Amazon S3 表,由于表位置由 Amazon S3 表目录管理,因此 SHOW TABLE 结果中将省略 LOCATION 子句。

创建表后,您可以使用 INSERT INTO 添加数据:

INSERT INTO

INSERT INTO <external_schema>.<table_name> [(column_name [, ...])] VALUES (...) INSERT INTO <external_schema>.<table_name> [(column_name [, ...])] (SELECT query) -- Using three-part notation for S3 table buckets: INSERT INTO "<table_bucket_name>@s3tablescatalog".<database_name>.<table_name> [(column_name [, ...])] VALUES (...) INSERT INTO "<table_bucket_name>@s3tablescatalog".<database_name>.<table_name> [(column_name [, ...])] (SELECT query)

您可以使用上述语法对现有 Iceberg 表执行 INSERT INTO。如果使用 VALUES 子句,则按 column_name 列出您为列提供的值,如果省略了 column_name 部分,则提供所有列的值。

将数据插入分区表时,将根据预定义的分区规范分布新行。如果 SELECT 查询由于任何原因失败,则查询将失败,并且不向 Iceberg 表中插入任何数据。

DELETE

Iceberg 表的 DELETE 查询使用 RMS 表中的现有 DELETE 语法:

[ WITH [RECURSIVE] common_table_expression [, common_table_expression , ...] ] DELETE [ FROM ] iceberg_table [ { USING } table_name, ... ] [ WHERE condition ]

对于 S3 表存储桶,您也可以使用三部分表示法。

[ WITH [RECURSIVE] common_table_expression [, common_table_expression , ...] ] DELETE [ FROM ] "<table_bucket_name>@s3tablescatalog".<database_name>.<table_name> [ { USING } table_name, ... ] [ WHERE condition ]

iceberg_table 可以使用 <external_schema>.<external_table_name> 格式进行引用,也可以使用三部分表示法来表示自动挂载目录。请参阅在 Amazon Redshift 中引用 Iceberg 表

USING 子句中的 table_name 可用来联接到目标表,以删除满足 WHERE 条件的行。table_name 可以是 Iceberg 表,也可以是 Amazon Redshift RMS 表。

由于 Iceberg 使用隐藏分区架构,因此用户可以使用 DELETE 查询来删除分区,实现与 Hive 表上的 ALTER TABLE ... DROP PARTITION ... 相同的效果。

例如,我们有如下所示的分区 Iceberg 表:

CREATE TABLE my_external_schema.lineitem (l_item_id int, l_ship_date varchar, ... ) USING ICEBERG LOCATION ... PARTITIONED BY l_ship_date;

然后我们可以使用如下查询轻松删除分区:

DELETE FROM my_external_schema.lineitem WHERE l_ship_date = '20251231';

对于这样的查询,Amazon Redshift 将优化执行,使其仅执行元数据操作并缩短执行循环时间。因此,与普通 DELETE 查询不同,仅限元数据的删除查询不会出现 EXPLAIN 中的执行步骤:

explain DELETE FROM my_external_schema.lineitem WHERE l_ship_date = '20251231'; QUERY PLAN ------------ "XN Seq Scan Metadata of my_external_schema.lineitem location: "s3://s3-path//table-location" format:ICEBERG (cost=0.00..0.01 rows=0 width=0)" (0 rows)

UPDATE

Iceberg 表的 UPDATE 查询语法与 RMS 表的现有 UPDATE 语法非常相似:

[ WITH [RECURSIVE] common_table_expression [, common_table_expression , ...] ] UPDATE iceberg_table [ [ AS ] alias ] SET column = { expression } [,...] [ FROM fromlist ] [ WHERE condition ]

对于 S3 表存储桶,您也可以使用三部分表示法。

[ WITH [RECURSIVE] common_table_expression [, common_table_expression , ...] ] UPDATE "<table_bucket_name>@s3tablescatalog".<database_name>.<table_name> [ [ AS ] alias ] SET column = { expression } [,...] [ FROM fromlist ] [ WHERE condition ]

iceberg_table 可以使用 <external_schema>.<external_table_name> 格式进行引用,也可以使用三部分表示法来表示自动挂载目录。请参阅在 Amazon Redshift 中引用 Iceberg 表

您可以通过引用其他表中的信息来更新表。在 FROM 子句中列出其他表,或者将子查询用作 WHERE 条件的一部分。源表可以是 Iceberg 表,也可以是 Amazon Redshift RMS 表。

UPDATE 也可以在分区表上运行。当 UPDATE 更改属于当前分区规范的列值时,新的更新行将根据新的更新值插入到新分区中。

例如,我们有一个如下所示的分区 Iceberg 表:

CREATE TABLE my_external_schema.lineitem (l_item_id int, l_ship_date varchar, ... ) USING ICEBERG LOCATION ... PARTITIONED BY l_ship_date; INSERT INTO my_external_schema.lineitem VALUES (10099, '20251231', ...);

在运行如下更新查询时:

UPDATE my_external_schema.lineitem SET l_ship_date = '20260101' WHERE l_item_id = 10099;

我们会将这个具有 l_item_id 10099 的行从分区移 20251231 到新分区 20260101

同样重要的是要注意,UPDATE 可能有多个候选值。请考虑以下查询:

CREATE TABLE my_ext_schema.t1(x1 int, y1 int) USING ICEBERG LOCATION ...; CREATE TABLE my_ext_schema.t2(x2 int, y2 int) USING ICEBERG LOCATION ...; INSERT INTO my_ext_schema.t1 VALUES (1,10), (2,20), (3,30); INSERT INTO my_ext_schema.t2 VALUES (2,40), (2,50); UPDATE my_ext_schema.t1 SET y1=y2 FROM my_ext_schema.t2 WHERE x1=x2;

在这种情况下,y1 可以是 40 或 50。结果是不确定的。您可以将配置参数 error_on_nondeterministic_update 设置为 true,以便在这种情况发生时强制查询出错。这与现有的 RMS 表 UPDATE 行为一致。有关更多信息,请参阅 error_on_nondeterministic_update

MERGE

MERGE 查询有条件地将源表中的行合并到目标表中。它与现有 RMS 表具有相同的 MERGE 查询语法:

MERGE INTO target_iceberg_table USING source_table [ [ AS ] alias ] ON match_condition [ WHEN MATCHED THEN { UPDATE SET col_name = { expr } [,...] | DELETE } WHEN NOT MATCHED THEN INSERT [ ( col_name [,...] ) ] VALUES ( { expr } [, ...] ) | REMOVE DUPLICATES ]

对于 S3 表存储桶,您也可以使用三部分表示法。

MERGE INTO "<table_bucket_name>@s3tablescatalog".<database_name>.<table_name> USING source_table [ [ AS ] alias ] ON match_condition [ WHEN MATCHED THEN { UPDATE SET col_name = { expr } [,...] | DELETE } WHEN NOT MATCHED THEN INSERT [ ( col_name [,...] ) ] VALUES ( { expr } [, ...] ) | REMOVE DUPLICATES ]

target_iceberg_table 可以使用 <external_schema>.<external_table_name> 格式进行引用,也可以使用三部分表示法来表示自动挂载目录。请参阅在 Amazon Redshift 中引用 Iceberg 表

source_table 可以是 Iceberg 表,也可以是 Amazon Redshift RMS 表。

使用 REMOVE DUPLICATES 时,MERGE 命令使用简化模式。有关简化模式的更多详细信息,请参阅原始 MERGE 命令文档

执行 MERGE 查询时,Amazon Redshift 会生成中间数据文件并将其存储在目标表的位置。这些文件将在查询结束时被垃圾回收。因此,MERGE 查询需要 Amazon S3 存储桶上的 DELETE 权限才能正常运行。如果垃圾回收操作失败,则会引发权限不足错误。对于 Amazon S3 表,垃圾回收由 Amazon S3 表类数据存储服务管理。因此,执行 MERGE 查询不需要 DELETE 权限。

DROP TABLE

要从目录中删除 Iceberg 表,请使用 DROP TABLE 命令:

DROP TABLE <external_schema>.<table_name>

您还可以对自动挂载目录使用三部分表示法:

DROP TABLE "<catalog_name>".<database_name>.<table_name>

使用 DROP 命令删除 Iceberg 表是仅对元数据执行的操作。如果表是 Amazon S3 表,则它会从 AWS Glue Data Catalog 和 Amazon S3 表目录中删除该表条目。Amazon Redshift 不会清理或删除表位置下的任何现有数据文件或元数据文件。您可以使用 AWS Glue 和 Amazon S3 表中的功能来移除孤立文件。对于 AWS Glue,请参阅删除孤立文件。对于 Amazon S3 表,请参阅表维护