Athena Partition과 Partition Projection
Context
S3에 적재된 raw event data를 Athena로 쿼리하려다가 partitioning이 안 된 테이블이라는 걸 알게 됐다. 쿼리 효율을 높이기 위해 partition projection을 적용했다.
What I Learned
1. Partition vs Index — 같은 범주가 아니다
| 항목 | Partition | Index |
|---|---|---|
| 목적 | 읽을 데이터 양 자체를 줄임 | 데이터 찾는 속도를 빠르게 |
| 데이터 위치 | 물리적으로 분리됨 | 그대로 있음 |
| 작동 방식 | 특정 partition만 스캔 | 전체 중에서 빠르게 lookup |
| 효과 | I/O 감소 (big data에서 핵심) | CPU/lookup 최적화 |
| Athena/S3 | 매우 중요 (거의 필수) | 없음 |
Partition은 데이터를 물리적으로 나눠 저장하고, 쿼리 시 일부만 읽도록 만드는 구조다.
s3://bucket/
├── event_date=2026-04-25/
├── event_date=2026-04-26/
└── event_date=2026-04-27/
WHERE event_date = '2026-04-27'
-- → 해당 폴더만 읽음 (partition pruning)
Athena는 index가 없다. 성능은 오직 얼마나 적은 S3 데이터를 읽느냐에 달려 있다.
partition 있음 → 필요한 파일만 읽음 → 빠름 + 저렴
partition 없음 → 전체 스캔 → 느림 + 비쌈
2. Partition Projection
partition 메타데이터를 실제로 저장하지 않고, 규칙으로 계산해서 사용하는 방식
전통적인 방식은 S3에 데이터를 올린 뒤 Glue Crawler를 돌리거나 ALTER TABLE ADD PARTITION을 실행해 메타데이터를 별도로 등록해야 한다.
Partition Projection은 DDL에 규칙만 정의하면 Athena가 경로를 직접 계산한다.
TBLPROPERTIES (
'projection.enabled'='true',
'projection.event_date.type'='date',
'projection.event_date.range'='2026-01-01,NOW',
'storage.location.template'='s3://bucket/${event_date}/'
)
쿼리 실행 시 내부 동작:
WHERE event_date = '2026-04-27'
→ template에 대입 → s3://bucket/2026-04-27/
→ 이 경로만 읽음 (metadata lookup 없음)
partnerid / eventtype / event_date 같이 partition 조합이 많을수록 projection이 유리하다. Crawler 없이 관리할 수 있다.
3. 실무 주의사항
반드시 partition 조건을 WHERE에 명시해야 한다.
-- ❌ 위험 — 모든 partition 조합을 스캔 시도 → 느림 / 비용 폭발
SELECT * FROM my_table LIMIT 100;
-- ✅ 올바른 방식
SELECT * FROM my_table
WHERE partnerid = 'A'
AND event_date = '2026-04-27';
injected 타입으로 설정된 partition 컬럼은 Athena가 가능한 값 목록을 모른다. 쿼리에서 반드시 직접 지정해야 한다.
Note
Projection은 partition 수가 많아질수록 강력하다. 반대로 WHERE에 partition 조건을 빠뜨리면 전체 스캔보다 더 나쁜 결과가 나올 수 있으니 팀 내 쿼리 가이드를 명확히 해두는 게 좋다.