

 Amazon Redshift는 패치 198부터 새 Python UDF 생성을 더 이상 지원하지 않습니다. 기존 Python UDF는 2026년 6월 30일까지 계속 작동합니다. 자세한 내용은 [블로그 게시물](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)을 참조하세요.

# SQL 명령
<a name="iceberg-writes-sql-syntax"></a>

Amazon Redshift의 Apache Iceberg 테이블은 데이터 레이크에서 대규모 분석 데이터세트를 관리하는 강력한 방법을 제공합니다. 이러한 테이블은 분석 워크로드의 성능을 높게 유지하면서 ACID 트랜잭션, 스키마 진화 및 시간 이동 기능을 지원합니다. Apache Iceberg 테이블을 사용하면 데이터를 효율적으로 구성 및 분할하고, 파일 형식 및 압축을 제어하고, 다른 AWS 서비스와 원활하게 통합할 수 있습니다.

`CREATE TABLE ... USING ICEBERG` 및 `CREATE TABLE ... USING ICEBERG AS SELECT` 명령을 사용하여 파티셔닝된 Iceberg 테이블과 파티셔닝되지 않은 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` 명령을 사용하면 됩니다. 이렇게 하면 테이블 등록만 제거됩니다. 실제 데이터는 별도로 삭제할 때까지 스토리지에 유지됩니다.

`DELETE`, `UPDATE` 및 `MERGE` 명령을 사용하여 기존 데이터를 수정할 수도 있습니다. `ALTER TABLE`과 같은 다른 모든 SQL 문은 아직 Iceberg 테이블에서 지원되지 않습니다.

Amazon Redshift에서 생성하지 않은 Iceberg 테이블로 쓸 수 있습니다. 그러나 몇 가지 제한 사항이 있습니다.
+ 테이블이 Iceberg v2 테이블이어야 합니다.
+ 테이블이 Parquet을 기본 데이터 형식으로 사용해야 합니다.
+ 테이블에 메타데이터 압축이 True로 설정되어 있지 않아야 합니다.
+ 테이블이 Write-Audit-Publish(WAP)를 활성화해서는 안 됩니다.

다음 섹션에서는 Amazon Redshift에서 Iceberg 테이블을 생성, 삽입, 수정 및 관리하기 위한 SQL 구문을 보여줍니다.

**Contents**
+ [CREATE TABLE](#iceberg-writes-create-table)
+ [CREATE TABLE AS SELECT](#iceberg-writes-create-table-as-select)
+ [SHOW TABLE](#iceberg-writes-show-table)
+ [INSERT INTO](#iceberg-writes-insert-into)
+ [DELETE](#iceberg-writes-delete)
+ [UPDATE](#iceberg-writes-update)
+ [MERGE](#iceberg-writes-merge)
+ [DROP TABLE](#iceberg-writes-drop-table)

## CREATE TABLE
<a name="iceberg-writes-create-table"></a>

```
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](https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_EXTERNAL_SCHEMA.html)를 참조하세요.

`LOCATION` 절은 새로 생성된 이 Iceberg 테이블의 테이블 위치를 정의합니다. Amazon S3 테이블의 경우, 테이블 위치는 Amazon S3 테이블 카탈로그(`s3tablescatalog`)에 의해 결정되므로 `LOCATION`을 지정할 수 없습니다.

다른 모든 경우에는 `LOCATION`이 필요하며 빈 위치여야 합니다. 즉, 동일한 버킷과 접두사를 공유하는 기존 Amazon S3 객체가 없어야 합니다. Amazon S3 버킷 리전이 Amazon Redshift 클러스터와 동일한 리전에 있어야 합니다.

하지만 AWS는 한 AWS 리전의 AWS Glue Data Catalog에 저장된 Iceberg 테이블의 데이터를 다른 AWS 리전으로 복제하는 방법을 제공하므로 쓰기 작업을 다른 리전으로 복제할 수 있습니다. 자세한 내용은 [AWS 리전에서 데이터 복제](https://docs.aws.amazon.com/prescriptive-guidance/latest/apache-iceberg-on-aws/best-practices-workloads.html#workloads-replication)를 참조하세요.

`PARTITIONED BY`는 Iceberg 테이블 파티션을 정의합니다. Amazon Redshift는 `void`를 제외한 모든 Iceberg v2 파티션 변환을 지원합니다. 지원되는 변환 목록은 다음과 같습니다.
+ ** -ID**
+ **버킷[N]**
+ **자르기[W]**
+ **년**
+ **개월**
+ **day**
+ **시간**

이러한 변환의 전체 정의와 호환되는 데이터 형식은 Apache Iceberg 설명서의 [파티션 변환](https://iceberg.apache.org/spec/#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 테이블에 대한 추가 테이블 속성을 정의합니다. 지원되는 유일한 테이블 속성은 기본 Parquet 데이터 파일 압축을 정의하는 `compression_type`입니다. 지정하지 않으면 `snappy`가 압축 코덱으로 사용됩니다. `compression_type`에 가능한 값은 `zstd`, `brotli`, `gzip`, `snappy`, `uncompressed`입니다.

**참고**  
`CREATE TABLE ... LIKE ...`는 Iceberg 테이블에서 지원되지 않습니다. Iceberg 테이블은 열 제약 조건과 RMS 테이블과 같은 열 속성도 지원하지 않습니다.

또는 `CREATE TABLE AS SELECT`를 사용하여 단일 작업으로 Iceberg 테이블을 생성하고 채울 수 있습니다.

## CREATE TABLE AS SELECT
<a name="iceberg-writes-create-table-as-select"></a>

```
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
```

이는 테이블을 `SELECT` 쿼리 결과로 채우는 `SELECT` 문이 뒤에 오는 `CREATE`를 제외하면 `CREATE TABLE` 문과 유사합니다.

열 데이터 형식은 `SELECT` 쿼리에 의해 결정되므로 이 `CREATE TABLE` 절에서는 더 이상 데이터 형식을 지정할 수 없습니다.

어떤 이유로든 `SELECT` 쿼리가 실패하면 이 쿼리가 실패하고 Iceberg 테이블이 생성되지 않습니다.

`SHOW TABLE`을 사용하여 Iceberg 테이블의 구조를 볼 수 있습니다.

## SHOW TABLE
<a name="iceberg-writes-show-table"></a>

```
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
<a name="iceberg-writes-insert-into"></a>

```
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)
```

위의 구문을 사용하여 `INSERT INTO` 기존 Iceberg 테이블을 사용할 수 있습니다. `VALUES` 절을 사용하는 경우 `column_name`에 나열된 열의 값을 제공하거나 `column_name` 파트가 생략된 경우 모든 열을 제공합니다.

데이터가 분할된 테이블에 삽입되면 사전 정의된 파티션 사양에 따라 새 행이 배포됩니다. 어떤 이유로든 `SELECT` 쿼리가 실패하면 쿼리가 실패하고 Iceberg 테이블에 데이터가 삽입되지 않습니다.

## DELETE
<a name="iceberg-writes-delete"></a>

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>}}` 양식을 사용하여 참조하거나 자동 탑재 카탈로그에 3파트 표기법을 사용할 수 있습니다. [Amazon Redshift에서 Iceberg 테이블 참조](https://docs.aws.amazon.com/redshift/latest/dg/referencing-iceberg-tables.html)를 참조하세요.

`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
<a name="iceberg-writes-update"></a>

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>}}` 양식을 사용하여 참조하거나 자동 탑재 카탈로그에 3파트 표기법을 사용할 수 있습니다. [Amazon Redshift에서 Iceberg 테이블 참조](https://docs.aws.amazon.com/redshift/latest/dg/referencing-iceberg-tables.html)를 참조하세요.

다른 테이블에 있는 정보를 참조하여 테이블을 업데이트할 수 있습니다. 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](https://docs.aws.amazon.com/redshift/latest/dg/r_error_on_nondeterministic_update.html)를 참조하세요.

## MERGE
<a name="iceberg-writes-merge"></a>

`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>}}` 양식을 사용하여 참조하거나 자동 탑재 카탈로그에 3파트 표기법을 사용할 수 있습니다. [Amazon Redshift에서 Iceberg 테이블 참조](https://docs.aws.amazon.com/redshift/latest/dg/referencing-iceberg-tables.html)를 참조하세요.

`{{source_table}}`은 Iceberg 테이블 또는 Amazon Redshift RMS 테이블일 수 있습니다.

`REMOVE DUPLICATES`를 사용하는 경우 `MERGE` 명령은 단순화된 모드를 사용합니다. 간소화된 모드에 대한 자세한 내용은 원본 `MERGE` [명령 문서](https://docs.aws.amazon.com/redshift/latest/dg/r_MERGE.html)를 참조하세요.

`MERGE` 쿼리를 실행하는 동안 Amazon Redshift는 중간 데이터 파일을 생성하여 대상 테이블 위치에 저장합니다. 이러한 파일은 쿼리가 끝날 때 가비지로 수집됩니다. 따라서 `MERGE` 쿼리가 제대로 작동하려면 Amazon S3 버킷에 대한 `DELETE` 권한이 필요합니다. 폐영역 회수 작업이 실패하면 권한 부족 오류가 발생합니다. Amazon S3 테이블의 경우 폐영역 회수는 Amazon S3 테이블 서비스에서 관리합니다. 따라서 `MERGE` 쿼리를 실행하는 데 `DELETE` 권한이 필요하지 않습니다.

## DROP TABLE
<a name="iceberg-writes-drop-table"></a>

카탈로그에서 Iceberg 테이블을 제거하려면 `DROP TABLE` 명령을 사용합니다.

```
DROP TABLE {{<external_schema>}}.{{<table_name>}}
```

자동 마운트된 카탈로그에서 세 부분으로 구성된 주석을 사용할 수도 있습니다.

```
DROP TABLE "{{<catalog_name>}}".{{<database_name>}}.{{<table_name>}}
```

Iceberg 테이블 삭제는 메타데이터 전용 작업입니다. Amazon S3 테이블인 경우 AWS Glue Data Catalog 및 Amazon S3 테이블 카탈로그에서 테이블 항목을 제거합니다. Amazon Redshift는 테이블 위치 아래의 기존 데이터 파일 또는 메타데이터 파일을 정리하거나 삭제하지 않습니다. AWS Glue 및 Amazon S3 테이블의 기능을 사용하여 분리된 파일을 제거할 수 있습니다. AWS Glue의 경우 [분리된 파일 삭제](https://docs.aws.amazon.com/glue/latest/dg/orphan-file-deletion.html)를 참조하세요. Amazon S3 테이블의 경우 [테이블 유지 관리](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-maintenance.html)를 참조하세요.