Athena 테이블 DDL 간단 정리

게시일 : 2023년 12월 25일    
# AWS # Athena

Athena 테이블 DDL에 대해 간단히 정리해본다.

데이터 타입

데이터 타입은 아래 링크에서 확인할 수 있다.

Data types in Amazon Athena - in AWS

ARRAY & STRUCT 타입

특별한 경우로는 ARRAY와 STRUCT 타입이 있다.

[1,2,3] => array<int>

{"a": 100, "b": "HELLO"} => struct<a:int,b:string>

{"a": 3.54, "b":["a","b"]} => struct<a:float,b:array<string>>

[{"a": 15341, "b": "2.121}, {"a": 2341, "b": 3.232}] => array<struct<a:bigint,b:double>>

참고로, SELECT 문에서 직접 사용하려면 다음처럼 사용한다. ( UNLOAD를 통해 데이터 타입을 변환해서 저장할 때 유용하다. )

STRUCT는 ROW라는 함수를 사용하고 CAST를 통해 STRUCT의 타입을 정의해주어야 한다. ( string 대신 varchar를 사용 )

SELECT ARRAY[1,2,3]

SELECT CAST(ROW('HELLO', 100) AS ROW(name varchar, age int))

ARRAY 타입 사용 시 주의할 점

Athena에서는 보통 Parquet 타입을 많이 사용한다. Parquet 타입은 empty array를 허용하지 않는다.

UNLOAD 아테나 쿼리를 사용해 parquet로 압축하기 위해서는 배열의 길이 확인 후 empty array를 NULL로 변환해야 한다.

cardinality: 배열 길이 함수

-- 배열 길이 확인
SELECT cardinality(ARRAY[1,2,3]) 
=> 3

SELECT CASE WHEN cardinality(col) = 0 THEN NULL ELSE col END AS col

CSV 데이터

skip.header.line.count : CSV의 header를 무시한다는 의미이다.

FIELDS TERMINATED BY : CSV의 구분자를 의미한다.

CREATE EXTERNAL TABLE [ DB ].[ 테이블 ](
  `A` int, 
  `B` string,
  `C` float,
)

ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY ',' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://[ 버킷 ]/[ PREFIX ]'

TBLPROPERTIES (
  'skip.header.line.count'='1'
)

JSON 데이터

ignore.malformed.json : 오류 데이터는 무시한다는 의미

CREATE EXTERNAL TABLE [ DB ].[ 테이블 ](
  ...
  )
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
WITH SERDEPROPERTIES ( 
  'ignore.malformed.json'='true') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'

LOCATION
    's3://[ 버킷 ]/[ PREFIX ]'

PARQUET 데이터

CREATE EXTERNAL TABLE [ DB ].[ 테이블 ](
  ...
  )

ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'

LOCATION
    's3://[ 버킷 ]/[ PREFIX ]'

파티션 관리

파티션된 테이블 정의

PARTITIONED BY 라는 부분을 작성해주면 된다.

CREATE EXTERNAL TABLE [ DB ].[ 테이블 ](
  ...
  )

PARTITIONED BY ( 
  `[ 파티션 ]` string,
)

ROW FORMAT SERDE 
    ...

테이블에 파티션 추가

ALTER TABLE [ DB ].[ 테이블 ] ADD IF NOT EXISTS 
PARTITION ([파티션] = '[ 값 ]') LOCATION 's3://[ 버킷 ]/[ PREFIX ]/[ 파티션 ]=[ 값 ]'

Projection Partitioning

파티션을 자동으로 추가하는 방법으로 파티션이 연속적인 숫자나 날짜일 때 사용한다.

아래는 파티션이 날짜인 경우 파티션명을 dt로 설정하고 적용한 예시이다.

CREATE EXTERNAL TABLE [ DB ].[ 테이블 ](
    ...
)

...

PARTITIONED BY ( 
  `dt` string
)

...

LOCATION
  's3://[ 버킷 ]/[ PREFIX ]'
TBLPROPERTIES (
  'projection.dt.format'='yyyy-MM-dd', 
  'projection.dt.interval'='1', 
  'projection.dt.interval.unit'='DAYS', 
  'projection.dt.range'='2023-01-01,NOW', 
  'projection.dt.type'='date',
  'storage.location.template'='s3://[ 버킷 ]/[ PREFIX ]/dt=${dt}'
)

References :