

# Amazon Athena의 데이터 형식
<a name="data-types"></a>

`CREATE TABLE`을 실행할 때 각 열에 포함할 수 있는 열 이름과 데이터 형식을 지정합니다. 생성한 테이블은 AWS Glue Data Catalog에 저장됩니다.

다른 쿼리 엔진과의 상호 운용성을 높이기 위해 Athena는 `CREATE TABLE`과 같은 DDL 문에 [Apache Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types) 데이터 유형 이름을 사용합니다. `SELECT`, `CTAS`, `INSERT INTO` 등과 같은 DML 쿼리의 경우 Athena는 [Trino](https://trino.io/docs/current/language/types.html) 데이터 유형 이름을 사용합니다. 다음 표는 Athena에서 지원되는 데이터 유형을 보여줍니다. DDL 및 DML 유형이 이름, 가용성 또는 구문 측면에서 다른 경우 별도의 열에 표시됩니다.


****  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/athena/latest/ug/data-types.html)

**Topics**
+ [데이터 유형 예제](data-types-examples.md)
+ [데이터 유형에 대한 고려 사항](data-types-considerations.md)
+ [타임스탬프 데이터 작업](data-types-timestamps.md)

# 데이터 유형 예제
<a name="data-types-examples"></a>

다음 표는 DML 데이터 유형에 대한 예제 리터럴을 보여줍니다.


****  

| 데이터 유형 | 예제 | 
| --- | --- | 
| BOOLEAN |  `true` `false `  | 
| TINYINT |  `TINYINT '123'`  | 
| SMALLINT |  `SMALLINT '123'`  | 
| INT, INTEGER |  `123456790`  | 
| BIGINT |  `BIGINT '1234567890'` `2147483648`  | 
| REAL |  `'123456.78'`  | 
| DOUBLE |  `1.234`  | 
| DECIMAL(precision, scale) |  `DECIMAL '123.456'`  | 
| CHAR, CHAR(length) |  `CHAR 'hello world'`, `CHAR 'hello ''world''!'`  | 
| VARCHAR, VARCHAR(length) |  `VARCHAR 'hello world'`, `VARCHAR 'hello ''world''!'`  | 
| VARBINARY |  `X'00 01 02'`  | 
| TIME, TIME(precision) |  `TIME '10:11:12'`, `TIME '10:11:12.345'`  | 
| TIME WITH TIME ZONE |  `TIME '10:11:12.345 -06:00'`  | 
| DATE |  `DATE '2024-03-25'`  | 
|  TIMESTAMP, TIMESTAMP WITHOUT TIME ZONE, TIMESTAMP(*precision*), TIMESTAMP(*precision*) WITHOUT TIME ZONE   |  `TIMESTAMP '2024-03-25 11:12:13'`, `TIMESTAMP '2024-03-25 11:12:13.456'`  | 
| TIMESTAMP WITH TIME ZONE, TIMESTAMP(precision) WITH TIME ZONE |  `TIMESTAMP '2024-03-25 11:12:13.456 Europe/Berlin'`  | 
| INTERVAL YEAR TO MONTH |  `INTERVAL '3' MONTH`  | 
| INTERVAL DAY TO SECOND |  `INTERVAL '2' DAY`  | 
| ARRAY[element\$1type] |  `ARRAY['one', 'two', 'three']`  | 
| MAP(key\$1type, value\$1type) |  `MAP(ARRAY['one', 'two', 'three'], ARRAY[1, 2, 3])` 맵은 키 배열과 값 배열로 생성됩니다. 다음 예제는 문자열을 정수로 매핑하는 테이블을 생성합니다. <pre>CREATE TABLE map_table(col1 map<string, integer>) LOCATION '...';<br />INSERT INTO map_table values(MAP(ARRAY['foo', 'bar'], ARRAY[1, 2]));</pre>  | 
| ROW(field\$1name\$11 field\$1type\$11, field\$1name\$12 field\$1type\$12, …) |  `ROW('one', 'two', 'three')` 이 방법으로 생성된 행에는 열 이름이 없습니다. 열 이름을 추가하려면 다음 예제와 같이 `CAST`를 사용할 수 있습니다. <pre>CAST(ROW(1, 2, 3) AS ROW(one INT, two INT, three INT))</pre>  | 
| JSON |  `JSON '{"one":1, "two": 2, "three": 3}'`  | 
| UUID |  `UUID '12345678-90ab-cdef-1234-567890abcdef'`  | 
| IPADDRESS |  `IPADDRESS '10.0.0.1'` `IPADDRESS '2001:db8::1'`  | 

# 데이터 유형에 대한 고려 사항
<a name="data-types-considerations"></a>

## 크기 제한
<a name="data-types-considerations-size"></a>

크기 제한이 지정되지 않은 데이터 유형의 경우 한 행의 모든 데이터에 대한 실제 제한은 32MB라는 점에 유의하세요. 자세한 설명은 [Amazon Athena의 SQL 쿼리에 대한 고려 사항 및 제한 사항](other-notable-limitations.md)에서 [Row or column size limitation](other-notable-limitations.md#sql-limitations-rowsize) 섹션을 참조하세요.

## CHAR 및 VARCHAR
<a name="data-types-considerations-char"></a>

`CHAR(n)` 값에는 항상 `n`개의 문자가 포함됩니다. 예를 들어, 'abc'를 `CHAR(7)`로 변환하면 4개의 후행 공백이 추가됩니다.

`CHAR` 값 비교에는 선행 공백과 후행 공백이 포함됩니다.

`CHAR` 또는 `VARCHAR`에 대해 길이가 지정되면 읽을 때 문자열이 지정된 길이만큼 잘립니다. 기본 데이터 문자열이 더 긴 경우 기본 데이터 문자열은 변경되지 않습니다.

`CHAR` 또는 `VARCHAR`에서 작은따옴표를 이스케이프하려면 추가로 작은 따옴표를 사용합니다.

문자열이 아닌 데이터 유형을 DML 쿼리의 문자열로 변환하려면 `VARCHAR` 데이터 유형으로 캐스팅합니다.

`substr` 함수를 사용하여 `CHAR` 데이터 유형에서 지정된 길이의 하위 문자열을 반환하려면 먼저 `CHAR` 값을 `VARCHAR`로 캐스팅해야 합니다. 다음 예제에서 `col1`은 `CHAR` 데이터 유형을 사용합니다.

```
substr(CAST(col1 AS VARCHAR), 1, 4)
```

## DECIMAL
<a name="data-types-considerations-decimal"></a>

특정 10진수 값이 있는 행을 선택하는 경우와 같이 `DECIMAL` 쿼리에서 10진수 값을 리터럴로 지정하려면 다음 예제와 같이 `SELECT` 유형을 지정하고 쿼리에서 10진수 값을 작은따옴표로 묶인 리터럴로 나열합니다.

```
SELECT * FROM my_table
WHERE decimal_value = DECIMAL '0.12'
```

```
SELECT DECIMAL '44.6' + DECIMAL '77.2'
```

# 타임스탬프 데이터 작업
<a name="data-types-timestamps"></a>

이 섹션에서는 Athena에서 타임스탬프 데이터를 작업할 때 고려해야 할 몇 가지 사항을 설명합니다.

**참고**  
이전 엔진 버전과 Athena 엔진 버전 3 사이에서 타임스탬프 처리가 조금 변경되었습니다. Athena 엔진 버전 3에서 발생할 수 있는 타임스탬프 관련 오류와 권장 솔루션은 [Athena 엔진 버전 3](engine-versions-reference-0003.md) 참조의 [타임스탬프 변경 사항](engine-versions-reference-0003.md#engine-versions-reference-0003-timestamp-changes) 섹션을 참조하세요.

## Amazon S3 객체에 타임스탬프 데이터를 쓰기 위한 형식
<a name="data-types-timestamps-writing-to-s3-objects"></a>

Amazon S3 객체에 타임스탬프 데이터를 써야 하는 형식은 사용하는 [SerDe 라이브러리](https://docs.aws.amazon.com/athena/latest/ug/supported-serdes.html)와 열 데이터 형식 모두에 따라 달라집니다.
+ 테이블 열 형식이 `DATE`인 경우 Athena는 데이터의 해당 열 또는 속성을 ISO 형식 `YYYY-MM-DD`의 문자열이거나 Parquet 또는 ORC와 같은 기본 제공 날짜 유형으로 예상합니다.
+ 테이블 열 형식이 `TIME`인 경우 Athena는 데이터의 해당 열 또는 속성을 ISO 형식 `HH:MM:SS`의 문자열이거나 Parquet 또는 ORC와 같은 기본 제공 시간 유형으로 예상합니다.
+ 테이블 열 형식이 `TIMESTAMP`인 경우 Athena는 데이터의 해당 열 또는 속성을 `YYYY-MM-DD HH:MM:SS.SSS` 형식의 문자열(날짜 및 시간 사이의 공백에 주의)이거나 Parquet, ORC 또는 Ion과 같은 기본 제공 시간 유형으로 예상합니다. 참고로 Athena는 유효하지 않은 타임스탬프(예: `0000-00-00 08:00:00.000`)에 대한 동작을 보장하지 않습니다.
**참고**  
OpenCSVSerDe 타임스탬프는 예외이며, 밀리초 분해능의 UNIX 에포크로 인코딩해야 합니다.

## 시간을 기준으로 파티셔닝된 데이터가 레코드의 타임스탬프 필드와 일치하는지 확인
<a name="data-types-timestamps-time-partitioned-data-and-timestamp-fields"></a>

데이터 생성자는 파티션 값이 파티션 내 데이터에 맞게 조정되었는지 확인해야 합니다. 예를 들어 데이터에 `timestamp` 속성이 있고 Firehose를 사용하여 Amazon S3로 데이터를 로드하는 경우 Firehose의 기본 파티셔닝은 12시간 형식의 시간에 기반하므로 [동적 파티셔닝](https://docs.aws.amazon.com/firehose/latest/dev/dynamic-partitioning.html)을 사용해야 합니다.

## 파티션 키의 데이터 형식으로 문자열 사용
<a name="data-types-timestamps-partition-key-types"></a>

성능상의 이유로 파티션 키의 데이터 유형으로 `STRING`을 사용하는 것이 좋습니다. `DATE` 유형을 사용할 때 Athena는 `YYYY-MM-DD` 형식의 파티션 값을 날짜로 인식하지만 이 경우 성능이 저하될 수 있습니다. 이러한 이유로 대신 파티션 키에 `STRING` 데이터 형식을 사용하는 것이 좋습니다.

## 시간을 기준으로 파티셔닝된 타임스탬프 필드에 대한 쿼리를 작성하는 방법
<a name="data-types-timestamps-how-to-write-queries-for-timestamp-fields-that-are-also-time-partitioned"></a>

시간을 기준으로 파티셔닝된 타임스탬프 필드에 대한 쿼리를 작성하는 방법은 쿼리하려는 테이블 유형에 따라 달라집니다.

### Hive 테이블
<a name="data-types-timestamps-hive-tables"></a>

Athena에서 가장 흔히 사용되는 Hive 테이블의 경우 쿼리 엔진은 열과 파티션 키 사이의 관계를 알지 못합니다. 따라서 항상 쿼리에 열과 파티션 키 모두에 대한 조건자를 추가해야 합니다.

예를 들어 `event_time` 열과 `event_date` 파티션 키가 있고 23:00 및 03:00 사이에 이벤트를 쿼리하려고 한다고 가정합니다. 이 경우 다음 예제와 같이 열과 파티션 키 모두에 대한 조건자를 쿼리에 포함해야 합니다.

```
WHERE event_time BETWEEN start_time AND end_time 
  AND event_date BETWEEN start_time_date AND end_time_date
```

### Iceberg 테이블
<a name="data-types-timestamps-iceberg-tables"></a>

Iceberg 테이블을 사용하면 쿼리를 단순화하는 계산된 파티션 값을 사용할 수 있습니다. 예를 들어 Iceberg 테이블이 다음과 같은 `PARTITIONED BY` 절을 사용하여 생성되었다고 가정합니다.

```
PARTITIONED BY (event_date month(event_time))
```

이 경우 쿼리 엔진은 `event_time` 조건자 값을 기반으로 파티션을 자동으로 정리합니다. 따라서 다음 예제와 같이 쿼리에서는 `event_time`에 대한 조건자만 지정하면 됩니다.

```
WHERE event_time BETWEEN start_time AND end_time
```

자세한 내용은 [Iceberg 테이블 생성](querying-iceberg-creating-tables.md) 섹션을 참조하세요.

타임스탬프 열에 Iceberg의 숨겨진 파티셔닝을 사용하는 경우 Iceberg는 타임스탬프 열에서 파생되고 보다 효과적인 파티셔닝을 위해 날짜로 변환되어 구성된 테이블 열에서 파티션을 생성할 수 있습니다. 예를 들어 타임스탬프 열 `event_time`에서 `event_date`를 생성하고 `event_date`에서 자동으로 파티셔닝할 수 있습니다. 이 경우 파티션 **유형**은 **날짜**입니다.

파티션을 사용하는 경우 쿼리 성능을 최적화하기 위해 종일 범위를 기준으로 필터링하여 조건자 푸시다운을 활성화합니다. 예를 들어 다음 쿼리는 하루 안에 속하더라도 범위를 단일 날짜 파티션으로 변환할 수 없으므로 푸시다운되지 않습니다.

```
WHERE event_time >= TIMESTAMP '2024-04-18 00:00:00' AND event_time < TIMESTAMP '2024-04-18 12:00:00'
```

대신 다음 예제와 같이 종일 범위를 사용하여 조건자 푸시다운을 허용하고 쿼리 성능을 개선합니다.

```
WHERE event_time >= TIMESTAMP '2024-04-18 00:00:00' AND event_time < TIMESTAMP '2024-04-19 00:00:00'
```

타임스탬프 일부가 `00:00:00`인 경우 `BETWEEN start_time AND end_time` 구문을 사용하거나 여러 일의 범위를 사용할 수도 있습니다.

자세한 내용은 [Trino 블로그 게시물](https://trino.io/blog/2023/04/11/date-predicates.html)을 참조하세요.