

# 스키마 업데이트
<a name="make-schema-updates"></a>

이 주제에서는 데이터를 실제로 변경하지 않고도 `CREATE TABLE` 문을 통해 스키마에서 가능한 몇 가지 변경 사항을 설명합니다. 스키마를 업데이트하기 위해 `ALTER TABLE` 명령을 사용할 수도 있지만 기존 테이블을 실제로 수정하지 않는 경우도 있습니다. 대신 원래 `CREATE TABLE` 문에서 사용한 스키마를 수정하는 새 이름의 테이블을 생성합니다.

예상되는 스키마의 변화에 따라 Athena 쿼리를 계속 사용하려면 호환되는 데이터 형식을 선택합니다.

CSV와 Parquet이라는 두 가지 형식으로 존재하는 `orders` 테이블에서 주문 정보를 읽는 애플리케이션을 살펴보겠습니다.

다음 예제에서는 Parquet 형식으로 테이블을 만듭니다.

```
CREATE EXTERNAL TABLE orders_parquet (
   `orderkey` int, 
   `orderstatus` string, 
   `totalprice` double, 
   `orderdate` string, 
   `orderpriority` string, 
   `clerk` string, 
   `shippriority` int
) STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_ parquet/';
```

다음 예제에서는 CSV 형식으로 동일한 테이블을 만듭니다.

```
CREATE EXTERNAL TABLE orders_csv (
   `orderkey` int, 
   `orderstatus` string, 
   `totalprice` double, 
   `orderdate` string, 
   `orderpriority` string, 
   `clerk` string, 
   `shippriority` int
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://amzn-s3-demo-bucket/orders_csv/';
```

다음 주제에서는 이러한 테이블 업데이트가 Athena 쿼리에 주는 영향을 알아봅니다.

**Topics**
+ [테이블의 시작 또는 중간에 열 추가](updates-add-columns-beginning-middle-of-table.md)
+ [테이블 끝에 열 추가](updates-add-columns-end-of-table.md)
+ [열 제거](updates-removing-columns.md)
+ [열 이름 변경하기](updates-renaming-columns.md)
+ [열 재정렬](updates-reordering-columns.md)
+ [열 데이터 형식 변경](updates-changing-column-type.md)

# 테이블의 시작 또는 중간에 열 추가
<a name="updates-add-columns-beginning-middle-of-table"></a>

열 추가는 가장 자주 발생하는 스키마 변경 중 하나입니다. 예를 들어 새 열을 추가하여 테이블을 새 데이터로 보강할 수 있습니다. 또는 기존 열의 소스가 변경된 경우 새 열을 추가하고, 이 열의 이전 버전을 유지하여 이러한 열을 사용하는 애플리케이션을 조정할 수 있습니다.

테이블의 시작 또는 중간에 열을 추가하고 기존 테이블에 대한 쿼리를 계속해서 실행하려면 Parquet 및 ORC(이름으로 읽도록 SerDe 속성을 설정한 경우), AVRO, JSON 형식을 사용합니다. 자세한 내용은 [Apache ORC 및 Apache Parquet의 인덱스 액세스에 대한 이해](handling-schema-updates-chapter.md#index-access) 섹션을 참조하세요.

CSV 및 TSV 형식의 테이블 시작 또는 중간에 열을 추가하지 마세요. 이러한 형식에서는 순서가 중요합니다. 그런 경우 열을 추가하면 파티션의 스키마가 변경될 경우 스키마 불일치 오류가 발생합니다.

 다음 예제에서는 JSON 데이터를 기반으로 테이블 중간에 `o_comment` 열을 추가하는 새 테이블을 생성합니다.

```
CREATE EXTERNAL TABLE orders_json_column_addition (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_comment` string, 
   `o_totalprice` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket/orders_json/';
```

# 테이블 끝에 열 추가
<a name="updates-add-columns-end-of-table"></a>

Parquet, ORC, Avro, JSON, CSV 및 TSV와 같이 Athena가 지원하는 형식 중 하나로 테이블을 생성하는 경우, 기존 열 뒤에(즉, 파티션 열 앞에) 열을 추가하는 `ALTER TABLE ADD COLUMNS` 문을 사용할 수 있습니다.

다음 예제에서는 파티션 열 앞의 `orders_parquet` 테이블 끝에 `comment` 열을 추가합니다.

```
ALTER TABLE orders_parquet ADD COLUMNS (comment string)
```

**참고**  
`ALTER TABLE ADD COLUMNS`를 실행한 후 Athena 쿼리 편집기에서 새 테이블 열을 보려면 편집기에서 테이블 목록을 수동으로 새로 고친 다음 테이블을 다시 확장합니다.

# 열 제거
<a name="updates-removing-columns"></a>

열에 더 이상 데이터가 없는 경우 테이블에서 열을 제거하거나 열의 데이터에 대한 액세스를 제한해야 할 수 있습니다.
+ JSON, Avro, Parquet 및 ORC 형식(이름으로 읽는 경우)의 테이블에서 열을 제거할 수 있습니다. 자세한 내용은 [Apache ORC 및 Apache Parquet의 인덱스 액세스에 대한 이해](handling-schema-updates-chapter.md#index-access) 섹션을 참조하세요.
+ Athena에서 이미 생성된 테이블을 유지하려면 CSV 및 TSV 형식의 테이블에서 열을 제거하지 않는 것이 좋습니다. 열을 제거하면 스키마가 차단되므로 제거된 열 없이 테이블을 다시 만들어야 합니다.

다음 예제에서는 Parquet 형식의 테이블에서 열 ``totalprice``를 제거하고 쿼리를 실행합니다. Athena에서 Parquet은 기본적으로 이름으로 읽습니다. 따라서 이름으로 읽기를 지정하는 SERDEPROPERTIES 구성을 생략했습니다. 스키마를 변경했더라도 다음 쿼리에 성공합니다.

```
CREATE EXTERNAL TABLE orders_parquet_column_removed (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_comment` string
) 
STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_parquet/';
```

# 열 이름 변경하기
<a name="updates-renaming-columns"></a>

철자를 수정하거나, 열 이름에 설명을 포함시키거나, 열이 재정렬되지 않도록 기존 열을 다시 사용하기 위해 테이블의 열 이름을 바꿔야 할 수 있습니다.

데이터를 CSV 및 TSV 형식 또는 Parquet 및 ORC 형식(인덱스로 읽도록 구성된 경우)으로 저장한 경우 열 이름을 변경할 수 있습니다. 자세한 내용은 [Apache ORC 및 Apache Parquet의 인덱스 액세스에 대한 이해](handling-schema-updates-chapter.md#index-access) 섹션을 참조하세요.

Athena는 스키마의 열 순서대로 CSV 및 TSV 형식의 데이터를 읽고 이를 동일한 순서로 반환합니다. 데이터를 열에 매핑할 때 열 이름을 사용하지 않기 때문에, Athena 쿼리를 중단하지 않고 CSV 또는 TSV 형식의 열 이름을 바꿀 수 있습니다.

열 이름을 바꾸는 한 가지 전략은 동일한 기본 데이터를 기반으로 새 테이블을 만들되 새 열 이름을 사용하는 것입니다. 다음 예제에서는 `orders_parquet_column_renamed`라는 새 `orders_parquet` 테이블을 만듭니다. 이 예제는 열 이름 ``o_totalprice``를 ``o_total_price``로 변경한 다음 Athena에서 다음 쿼리를 실행합니다.

```
CREATE EXTERNAL TABLE orders_parquet_column_renamed (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_total_price` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_comment` string
) 
STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_parquet/';
```

Parquet 테이블의 경우 다음 쿼리가 실행되지만 인덱스 대신 이름으로 열에 액세스(Parquet의 기본값)하므로 이름을 바꾼 열에 데이터가 표시되지 않습니다.

```
SELECT * 
FROM orders_parquet_column_renamed;
```

CSV 형식의 테이블이 있는 쿼리는 비슷하게 보입니다:

```
CREATE EXTERNAL TABLE orders_csv_column_renamed (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_total_price` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_comment` string
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://amzn-s3-demo-bucket/orders_csv/';
```

CSV 테이블의 경우, 다음 쿼리가 실행되고 이름이 바뀐 열을 포함한 모든 열에 데이터가 표시됩니다:

```
SELECT * 
FROM orders_csv_column_renamed;
```

# 열 재정렬
<a name="updates-reordering-columns"></a>

JSON 또는 Parquet과 같이 기본적으로 이름으로 읽는 형식의 데이터가 있는 테이블의 경우에만 열을 재정렬할 수 있습니다. 필요한 경우 ORC를 이름으로 읽도록 지정할 수도 있습니다. 자세한 내용은 [Apache ORC 및 Apache Parquet의 인덱스 액세스에 대한 이해](handling-schema-updates-chapter.md#index-access) 섹션을 참조하세요.

다음 예제에서는 열 순서가 다른 새 테이블을 생성합니다.

```
CREATE EXTERNAL TABLE orders_parquet_columns_reordered (
   `o_comment` string,
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderpriority` string, 
   `o_orderstatus` string, 
   `o_clerk` string, 
   `o_shippriority` int, 
   `o_orderdate` string
) 
STORED AS PARQUET
LOCATION 's3://amzn-s3-demo-bucket/orders_parquet/';
```

# 열 데이터 형식 변경
<a name="updates-changing-column-type"></a>

기존 유형에 필요한 양의 정보를 더 이상 보관할 수 없는 경우 다른 열 유형을 사용하는 것이 좋습니다. 예를 들어 ID 열의 값은 `INT` 데이터 형식의 크기를 초과할 수 있으므로 `BIGINT` 데이터 형식을 사용해야 합니다.

## 고려 사항
<a name="updates-changing-column-type-considerations"></a>

열에 대해 다른 데이터 형식을 사용하려는 경우 다음 사항을 고려해야 합니다.
+ 대부분의 경우 열의 데이터 형식을 직접 변경할 수는 없습니다. 대신 Athena 테이블을 다시 생성하고 새 데이터 형식으로 열을 정의합니다.
+ 특정 데이터 형식만 다른 데이터 형식으로 읽을 수 있습니다. 처리할 수 있는 데이터 형식은 본 섹션의 테이블을 참조하세요.
+ Parquet 및 ORC의 데이터인 경우 테이블이 파티셔닝되지 않으면 열에 대해 다른 데이터 형식을 사용할 수 없습니다.
+ Parquet 및 ORC 형식의 분할된 테이블의 경우 파티션의 열 형식은 다른 파티션의 열 형식과 다를 수 있으며, Athena는 가능하다면 원하는 형식으로 `CAST`합니다. 자세한 내용은 [파티션이 있는 테이블의 스키마 불일치 오류 방지](updates-and-partitions.md#partitions-dealing-with-schema-mismatch-errors) 섹션을 참조하세요.
+ [LazySimpleSerDe](lazy-simple-serde.md)를 사용하여 생성한 테이블의 경우에만 `ALTER TABLE REPLACE COLUMNS` 문을 사용하여 기존 열을 다른 데이터 형식으로 바꿀 수 있지만 유지하려는 기존 열도 모두 해당 명령문에서 다시 정의해야 합니다. 그렇지 않으면 해당 열이 삭제됩니다. 자세한 내용은 [ALTER TABLE REPLACE COLUMNS](alter-table-replace-columns.md) 섹션을 참조하세요.
+ Apache Iceberg 테이블의 경우에만 [ALTER TABLE CHANGE COLUMN](querying-iceberg-alter-table-change-column.md) 문을 사용하여 열의 데이터 형식을 변경할 수 있습니다. `ALTER TABLE REPLACE COLUMNS`는 Iceberg 테이블에서 지원되지 않습니다. 자세한 내용은 [Iceberg 테이블 스키마 개선](querying-iceberg-evolving-table-schema.md) 섹션을 참조하세요.

**중요**  
데이터 형식 변환을 수행하기 전에 쿼리를 테스트 및 확인하는 것이 좋습니다. Athena에서 대상 데이터 형식을 사용할 수 없는 경우 `CREATE TABLE` 쿼리에 실패할 수 있습니다.

## 호환되는 데이터 형식 사용
<a name="updates-changing-column-type-use-compatible-data-types"></a>

가능하면 호환되는 데이터 형식을 사용하세요. 다음 표에는 다른 데이터 형식으로 처리될 수 있는 데이터 형식이 나열되어 있습니다.


| 원래 데이터 형식 | 사용 가능한 대상 데이터 형식 | 
| --- | --- | 
| STRING | BYTE, TINYINT, SMALLINT, INT, BIGINT | 
| BYTE | TINYINT, SMALLINT, INT, BIGINT | 
| TINYINT | SMALLINT, INT, BIGINT | 
| SMALLINT | INT, BIGINT | 
| INT | BIGINT | 
| FLOAT | DOUBLE | 

다음 예제에서는 원래 `orders_json` 테이블에 대해 `CREATE TABLE` 문을 사용하여 `orders_json_bigint`라는 새 테이블을 생성합니다. 새 테이블은 `INT` 대신 `BIGINT`를 ``o_shippriority`` 열의 데이터 형식으로 사용합니다.

```
CREATE EXTERNAL TABLE orders_json_bigint (
   `o_orderkey` int, 
   `o_custkey` int, 
   `o_orderstatus` string, 
   `o_totalprice` double, 
   `o_orderdate` string, 
   `o_orderpriority` string, 
   `o_clerk` string, 
   `o_shippriority` BIGINT
) 
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://amzn-s3-demo-bucket/orders_json';
```

데이터 형식이 변경되기 전에 원래 `SELECT` 쿼리와 비슷한 다음 쿼리가 실행됩니다:

```
Select * from orders_json 
LIMIT 10;
```