Context

S3에 적재된 raw event data를 Athena로 쿼리하려다가 partitioning이 안 된 테이블이라는 걸 알게 됐다. 쿼리 효율을 높이기 위해 partition projection을 적용했다.

What I Learned

1. Partition vs Index — 같은 범주가 아니다

항목PartitionIndex
목적읽을 데이터 양 자체를 줄임데이터 찾는 속도를 빠르게
데이터 위치물리적으로 분리됨그대로 있음
작동 방식특정 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 조건을 빠뜨리면 전체 스캔보다 더 나쁜 결과가 나올 수 있으니 팀 내 쿼리 가이드를 명확히 해두는 게 좋다.

← All TIL