Amazon Athena 설정
Amazon Athena 설정
dbt v1 및 dbt 플랫폼용 Amazon Athena 어댑터의 참조 문서예요. 모델, 스냅샷, AWS Lake Formation 통합, Python 모델, 계약(contracts) 등 Athena에서 dbt를 쓸 때 필요한 설정 전반을 다뤄요.
출처: 문서
본문
모델 (Models)
테이블 설정 (Table configuration)
테이블 materialization과 관련된 주요 파라미터는 다음과 같아요:
| Parameter | Default | Description |
|---|---|---|
| external_location | None | 테이블이 저장되는 전체 S3 경로. 증분 모델에서만 동작하고, ha가 true인 Hive 테이블에서는 동작하지 않아요. |
| partitioned_by | None | 테이블이 파티셔닝되는 컬럼 배열. 현재 100개 파티션으로 제한돼요. |
| bucketed_by | None | 데이터를 버킷팅할 컬럼 배열. Iceberg를 사용하면 무시돼요. |
| bucket_count | None | 데이터 버킷팅에 사용할 버킷 수. Iceberg를 사용하면 이 파라미터는 무시돼요. |
| table_type | Hive | 테이블의 유형. hive 또는 iceberg를 지원해요. |
| ha | False | 고가용성(high-availability) 방식으로 테이블을 빌드해요. Hive 테이블에서만 사용할 수 있어요. |
| format | Parquet | 테이블의 데이터 형식. ORC, PARQUET, AVRO, JSON, TEXTFILE을 지원해요. |
| write_compression | None | 압축을 허용하는 모든 스토리지 형식에 대한 압축 유형. |
| field_delimeter | None | format이 TEXTFILE일 때 사용할 사용자 정의 필드 구분자. |
| table_properties | N/A | 테이블에 추가할 테이블 속성. Iceberg에서만 사용돼요. |
| native_drop | N/A | relation drop 작업이 직접 Glue API 호출이 아닌 SQL로 수행돼요. S3에서 데이터를 관리하기 위한 S3 호출은 없어요. S3의 데이터는 Iceberg 테이블에 대해서만 정리돼요. 자세한 내용은 AWS 문서를 참고하세요. Iceberg DROP TABLE 작업은 60초보다 오래 걸리면 타임아웃될 수 있어요. |
| seed_by_insert | False | SQL insert 문으로 seed를 생성해요. 큰 seed 파일은 Athena 262144 바이트 제한을 초과할 수 없어요. |
| force_batch | False | 테이블 생성을 배치 insert 모드로 직접 실행해요. 파티션 제한 때문에 표준 테이블 생성이 실패할 때 유용해요. |
| unique_tmp_table_suffix | False | Hive 테이블에서 insert overwrite를 사용하는 증분 모델의 "__dbt_tmp table" 접미사를 고유한 UUID로 대체해요. |
| temp_schema | None | 증분 모델 실행에 사용되는 임시 create 문을 보관할 스키마를 정의해요. 스키마는 없으면 모델의 대상 데이터베이스에 생성돼요. |
| lf_tags_config | None | 테이블과 컬럼에 연결할 AWS Lake Formation 태그. 기존 태그는 제거돼요. |
| lf_inherited_tags | None | 데이터베이스 레벨에서 상속받아 lf_tags_config에 정의된 태그 할당 중에 제거되지 않아야 할 Lake Formation 태그 키 목록. |
| lf_grants | None | data_cell 필터를 위한 Lake Formation grants 설정. |
lf_tags_config 상세:
enabled(기본값false): 모델에 대해 LF 태그 관리를 활성화할지 여부tags: 모델에 할당할 태그와 값 딕셔너리tags_columns: 태그 키, 값, 할당할 컬럼 목록을 담은 딕셔너리
예시 config(증분 + Iceberg + LF 태그):
{{
config(
materialized = 'incremental',
incremental_strategy = 'append',
on_schema_change = 'append_new_columns',
table_type = 'iceberg',
schema = 'test_schema',
lf_tags_config = {
'enabled': true,
'tags': {
'tag1': 'value1',
'tag2': 'value2'
},
'tags_columns': {
'tag1': {
'value1': ['column1', 'column2'],
'value2': ['column3', 'column4']
}
},
'inherited_tags': ['tag1', 'tag2']
}
)
}}
설정 예시 (Configuration examples)
프로젝트 YAML이나 property 파일, SQL config 블록에서 위 파라미터들을 설정할 수 있어요. dbt_project.yml에서는 프로젝트 또는 모델 그룹 단위로, property 파일에서는 모델 단위로 설정해요.
테이블 위치 (Table location)
테이블의 저장 위치는 다음 조건에 따라 우선순위로 결정돼요:
external_location이 정의돼 있으면 그 값이 사용돼요.s3_data_dir이 정의돼 있으면 그 경로와s3_data_naming에 따라 경로가 결정돼요.s3_data_dir이 정의돼 있지 않으면 데이터는{s3_staging_dir}/tables/아래에 저장돼요.
s3_data_naming에 사용할 수 있는 옵션:
unique:{s3_data_dir}/{uuid4()}/table:{s3_data_dir}/{table}/table_unique:{s3_data_dir}/{table}/{uuid4()}/schema_table:{s3_data_dir}/{schema}/{table}/schema_table_unique:{s3_data_dir}/{schema}/{table}/{uuid4()}/
s3_data_naming을 프로파일의 target에서 전역 설정하거나, 테이블 설정에서 덮어쓰거나, dbt_project.yml에서 모델 그룹 단위로 설정할 수 있어요.
참고: 기본 출력 위치가 구성된 workgroup을 사용한다면 s3_data_naming은 구성된 버킷을 무시하고 workgroup에 설정된 위치를 사용해요.
증분 모델 (Incremental models)
지원되는 증분 모델 전략은 다음과 같아요:
insert_overwrite(기본값): 대상 테이블에서 겹치는 파티션을 삭제한 뒤 소스의 새 레코드를 삽입해요. 이 전략은partitioned_by키워드에 의존해요! 파티션이 정의되지 않으면 dbt는append전략으로 대체해요.append: 기존 데이터를 업데이트·삭제·덮어쓰지 않고 새 레코드만 삽입해요. 중복 데이터가 있을 수 있어요(로그나 이력 데이터에 좋아요).merge: Iceberg 테이블에서 행을 조건부로 업데이트·삭제·삽입해요.unique_key와 함께 사용돼요. Iceberg에서만 사용할 수 있어요.
Iceberg 모델을 쓸 때 이 제한사항을 고려하세요:
- 증분 Iceberg 모델 — 스키마 변경 시 모든 컬럼을 동기화해요. 파티셔닝에 사용되는 컬럼은 증분 새로고침으로 제거할 수 없으니 모델을 완전히 새로고침해야 해요.
스키마 변경 (On schema change)
on_schema_change 옵션은 증분 모델에서 스키마의 변경을 반영해요. 설정할 수 있는 값은:
ignore(기본값)failappend_new_columnssync_all_columns
자세한 내용은 "What if the columns of my incremental model change" 문서를 참고하세요.
Iceberg
어댑터는 Iceberg에 대한 테이블 materialization을 지원해요. 예를 들어:
{{ config(
materialized = 'table',
table_type = 'iceberg',
format = 'parquet',
partitioned_by = ['bucket(user_id, 5)'],
table_properties = {
'optimize_rewrite_delete_file_threshold': '2'
}
) }}
select
'A' as user_id,
'pi' as name,
'active' as status,
17.89 as cost,
1 as quantity,
100000000 as quantity_big,
current_date as my_date
Iceberg는 버킷팅을 숨겨진 파티션(hidden partitions)으로 지원해요. partitioned_by 설정으로 특정 버킷팅 조건을 추가할 수 있어요.
Iceberg는 데이터 형식으로 PARQUET, AVRO, ORC를 지원해요.
Iceberg를 증분으로 사용할 때 지원되는 전략:
append: 새 레코드가 테이블에 추가돼요(중복이 발생할 수 있어요).merge: 새 레코드와 기존 레코드가 추가되는 update·insert(그리고 선택적으로 delete)를 수행해요. Athena engine version 3에서만 사용할 수 있어요.unique_key(필수): 소스와 대상 테이블 레코드를 정의하는 고유 컬럼.incremental_predicates(선택): merge 문에서 사용자 정의 join 절을 가능하게 하는 SQL 조건. 대상 테이블의 predicate pushdown을 통해 성능을 개선해요.delete_condition(선택): 삭제할 레코드를 식별하는 SQL 조건.update_condition(선택): 업데이트할 레코드를 식별하는 SQL 조건.insert_condition(선택): 삽입할 레코드를 식별하는 SQL 조건.
고가용성(HA) 테이블
현재 테이블 materialization 구현은 대상 테이블이 drop되고 다시 생성돼서 다운타임이 발생할 수 있어요. 덜 파괴적인 동작을 위해 테이블 materialized 모델에서 ha 설정을 사용할 수 있어요. 이는 glue catalog의 테이블 버전 기능을 활용해서 임시 테이블을 만들고 대상 테이블을 임시 테이블의 위치로 swap해요. 이 materialization은 table_type=hive에서만 사용할 수 있고 고유한 위치가 필요해요. Iceberg의 경우 고가용성이 기본이에요.
기본적으로 이 materialization은 마지막 4개의 테이블 버전을 유지하는데, versions_to_keep을 설정해 바꿀 수 있어요.
HA 알려진 문제 (HA known issues)
- 파티션이 있는 테이블과 없는 테이블 간에 swap할 때 약간의 다운타임이 있을 수 있어요. 더 높은 성능이 필요하면 파티션 대신 버킷팅을 고려하세요.
- 기본적으로 Glue는 버전을 내부적으로 "복제"해서 테이블의 마지막 두 버전이 같은 위치를 가리켜요.
versions_to_keep >= 4로 설정하는 것을 권장해요. 이렇게 하면 더 오래된 위치가 제거되는 것을 피할 수 있어요.
parquet 파일 삭제 방지 (Avoid deleting parquet files)
dbt 모델이 AWS Glue catalog에 있는 기존 테이블과 같은 이름이면, dbt-athena 어댑터는 해당 테이블의 S3 위치에 있는 파일을 삭제한 뒤 모델의 SQL로 테이블을 다시 생성해요.
모델이 기존 테이블과 같은 S3 위치를 사용하도록 구성되면 어댑터가 데이터를 삭제할 수도 있어요. 이 경우 설정 중 충돌을 피하기 위해 새 테이블을 만들기 전에 폴더를 비워요.
모델을 drop할 때 dbt-athena 어댑터는 관련 S3 데이터와 Glue catalog 항목을 함께 정리해요. 실수로 원본 데이터를 삭제하지 않도록 주의하세요.
Glue data catalog 업데이트
changed to config in v1.10 and backported to 1.9
스냅샷 (Snapshots)
어댑터는 스냅샷 materialization을 지원해요. timestamp와 check 전략을 모두 지원해요. 스냅샷을 만들려면 snapshots 디렉터리에 스냅샷 파일을 생성하세요. 디렉터리가 없다면 만들어야 해요.
Timestamp 전략 (Timestamp strategy)
사용 방법에 대한 자세한 내용은 Timestamp strategy 문서를 참고하세요.
Check 전략 (Check strategy)
사용 방법에 대한 자세한 내용은 Check strategy 문서를 참고하세요.
하드 삭제 (Hard deletes)
materialization은 하드 삭제(hard deletes) 무효화도 지원해요. 사용법은 Hard deletes 문서를 참고하세요.
스냅샷 알려진 문제 (Snapshots known issues)
- 테이블, 스키마, 데이터베이스 이름은 소문자만 사용해야 해요.
- 잠재적 충돌을 피하려면 대상 환경에 dbt-athena-adapter가 설치되어 있지 않은지 확인하세요.
- 스냅샷은 소스 테이블의 컬럼 drop을 지원하지 않아요. 컬럼을 drop했다면 스냅샷에서도 해당 컬럼을 drop해야 해요. 또 다른 해결책은 스냅샷 정의에서 컬럼을 NULL로 만들어 이력을 보존하는 거예요.
AWS Lake Formation 통합 (AWS Lake Formation integration)
어댑터가 AWS Lake Formation 태그 관리를 구현하는 방식은 다음과 같아요:
lf_tags_config파라미터로 LF 태그 관리를 활성화해요. 기본적으로 비활성화되어 있어요.- 활성화하면 LF 태그가 모든 dbt 실행에서 업데이트돼요.
- 먼저 상속 문제를 피하기 위해 컬럼의 모든 lf-tags가 제거돼요.
- 그다음 테이블에서 중복된 lf-tags를 모두 제거하고 테이블 설정의 실제 태그를 적용해요.
- 마지막으로 컬럼에 대한 lf-tags가 적용돼요.
다음 점을 이해하는 것이 중요해요:
- dbt는 데이터베이스에 대한 lf-tags를 관리하지 않아요.
- dbt는 Lake Formation 권한을 관리하지 않아요.
그래서 이를 직접 처리하거나 terraform, AWS CDK 같은 자동화 도구를 직접 사용해야 해요. 자세한 내용은 다음을 참고하세요:
- terraform aws_lakeformation_permissions
- terraform aws_lakeformation_resource_lf_tags
Python 모델 (Python models)
어댑터는 spark를 사용한 Python 모델을 지원해요.
사전 요구사항 (Prerequisites)
- Athena에 Spark 활성화 workgroup이 생성되어 있어야 해요.
- Spark 실행 역할이 Athena, Glue, S3에 대한 접근 권한을 부여받아야 해요.
- Spark workgroup이
~/.dbt/profiles.yml파일에 추가되어야 하고, 사용할 프로필이dbt_project.yml에서 참조되어야 해요.
Spark별 테이블 설정 (Spark-specific table configuration)
| Configuration | Default | Description |
|---|---|---|
| timeout | 43200 | 각 Python 모델 실행에 대한 타임아웃(초). 기본값은 12시간/43200초. |
| spark_encryption | False | true로 설정하면 Spark가 로컬에 저장하는 데이터와 Spark 노드 간 전송 데이터를 암호화해요. |
| spark_cross_account_catalog | False | Spark Athena workgroup을 사용할 때 기본적으로 같은 AWS 계정의 catalog에만 쿼리할 수 있어요. true로 설정하면 외부 AWS 계정의 다른 catalog를 쿼리할 수 있어요. 외부 계정의 외부 테이블에 접근하려면 external_catalog_id/database.table 문법을 사용해요(예: 999999999999/mydatabase.cloudfront_logs, 여기서 999999999999는 외부 catalog ID). |
| spark_requester_pays | False | true로 설정하면 Amazon S3 버킷이 requester pays로 구성됐을 때 쿼리를 실행하는 사용자 계정이 데이터 접근·전송 비용을 부담해요. |
Spark 참고 (Spark notes)
- ...
예시 모델 (Example models)
import pandas as pd
def model(dbt, session):
dbt.config(materialized="table")
model_df = pd.DataFrame({"A": [1, 2, 3, 4]})
return model_df
Python 모델의 알려진 문제 (Known issues in Python models)
- ...
계약 (Contracts)
어댑터는 contract 정의를 부분적으로 지원해요:
data_type은 지원되지만 복합 타입에 대해서는 조정이 필요해요. 타입은 체크되지 않더라도 완전히 지정해야 해요(예:array<int>). 실제로 dbt가 권장하는 것처럼 더 넓은 타입(array, map, int, varchar)만 비교해요. 완전한 정의는 Athena에 정의된 데이터 타입이 올바른지 확인하는 데 사용돼요(사전 검사).- 어댑터는 constraints를 지원하지 않아요. Athena에는 constraint 개념이 없기 때문이에요.
더 알아보기 (Learn more)
- 리소스 설정 전체 목록은 Resource configurations 문서를 참고하세요.
- Athena 증분 모델 전략과 제한사항은 dbt-athena-adapter 문서 및 공식 Athena 문서를 참고하세요.