year=, month= 같은 키=값 형식의 폴더 이름을 Hive 스타일 파티셔닝이라 부른다. Glue Crawler와 Athena가 이 규칙을 자동 인식해 파티션 컬럼으로 등록한다.
-- 파티션 키로 필터하면 해당 파티션의 Parquet만 스캔된다SELECT customer_id, COUNT(*) AS cntFROM ml_datalake.eventsWHERE year = '2026' AND month = '06' AND day = '25'GROUP BY customer_id;
파티션 키를 고르는 기준 — 잘못 고르면 효과가 0이다.
상황
결과
대응
자주 필터하는 컬럼으로 파티션
프루닝 발동, 스캔량 급감
이상적
거의 필터하지 않는 컬럼으로 파티션
항상 풀스캔
파티션 키 재설계
카디널리티가 너무 높음(초 단위, ID)
작은 파일 수백만 개, 메타데이터 폭증
상위 단위(일·월)로 묶기
카디널리티가 너무 낮음(값 2개)
프루닝 효과 미미
다른 키 고려
파티셔닝의 효과는 "파티션 키를 쿼리 조건에 쓸 때만" 나타난다. 날짜로 파티션했는데 정작 쿼리가 WHERE customer_id = ...로만 필터하면 모든 날짜 파티션을 풀스캔한다. 동시에 너무 잘게 쪼개면(예: 초 단위) 작은 파일이 수백만 개로 늘어 메타데이터 오버헤드와 "small files problem"이 생긴다. 보통 날짜(년/월/일) 또는 지역 같은 중간 카디널리티 컬럼이 적정선이다.
ML 데이터 저장에서 포맷 선택은 비용·속도에 직결된다. 핵심은 행 기반(row-oriented)과 열 기반(columnar)의 차이다.
포맷
방식
특징
ML 적합도
CSV
행 기반, 텍스트
사람이 읽기 쉬움, 스키마 없음, 비효율
낮음
JSON
행 기반, 텍스트
중첩 구조, 장황함
낮음
Parquet
열 기반, 바이너리
컬럼 단위 압축·스캔, 스키마 포함
높음
ORC
열 기반, 바이너리
Parquet과 유사, Hive 친화
높음
RecordIO
바이너리
SageMaker 빌트인 알고리즘 입력 포맷
학습 전용
Parquet이 분석·ML의 사실상 표준인 이유는 셋이다.
열 기반이라 필요한 컬럼만 읽어 I/O가 적다.
컬럼 단위로 압축률이 높다(같은 타입 값이 모여 있어서).
스키마와 통계(min/max)를 파일에 담아 불필요한 블록을 건너뛴다.
import pandas as pddf = pd.read_csv("s3://raw/events.csv")# Parquet으로 변환 + Snappy 압축 (Athena/SageMaker가 빠르게 읽음)df.to_parquet( "s3://ml-datalake/curated/events.parquet", engine="pyarrow", compression="snappy",)
압축 코덱 선택
코덱
압축률
속도
분할 가능
적합
Snappy
중간
빠름
Parquet 내부에서 가능
자주 읽는 학습·쿼리 데이터(기본값)
GZIP
높음
느림(CPU↑)
Parquet 내부에선 가능
드물게 읽는 아카이브
GZIP + CSV/JSON
높음
느림
불가능
병렬 처리에 부적합
Snappy는 압축률은 중간이지만 압축/해제가 빨라 쿼리·학습처럼 자주 읽는 데이터에 적합하다(Parquet 기본값). Gzip은 압축률이 높아 저장 비용을 줄이지만 CPU를 더 쓴다 — 자주 안 읽는 아카이브에 맞다. ML 학습 데이터는 반복적으로 읽으므로 보통 Snappy + Parquet 조합이 정답이다.
⚠️ 함정: "압축하면 무조건 좋다"가 아니다. CSV/JSON을 Gzip으로 압축하면 파일이 분할 불가능(non-splittable)해져, 여러 워커가 한 파일을 병렬로 나눠 읽지 못한다. Parquet은 내부 블록(row group) 단위로 분할 가능해 분산 학습·쿼리에서 병렬성을 유지한다. 큰 데이터를 다룰 땐 "압축 여부"보다 "분할 가능 포맷인가"가 더 중요하다.
[Gzip CSV 1개 파일] 워커1 ████████████████ 워커2 (놀고 있음)
→ 하나의 워커가 순차로 전부 읽어야 함
[Parquet 여러 샤드] 워커1 ████ 워커2 ████ 워커3 ████ 워커4 ████
→ row group·파일 단위로 나눠 동시에 읽음
데이터를 S3에 둘 때는 여러 개의 적당한 크기 파일(샤드)로 나누는 것도 중요하다. 단일 거대 파일은 분산 학습에서 여러 인스턴스가 나눠 읽기 어렵다. SageMaker는 ShardedByS3Key 분배 방식으로 파일들을 인스턴스에 나눠 줄 수 있다.
분배 방식
동작
언제
FullyReplicated
모든 인스턴스가 전체 데이터를 받음
검증셋, 작은 데이터
ShardedByS3Key
인스턴스마다 다른 객체만 받음
분산 학습(단, 객체가 여러 개여야 함)
⚠️ 함정: ShardedByS3Key를 켰다고 끝이 아니다. 샤딩은 S3 객체 단위라, 단일 100GB 파일 하나에 걸면 아무 분배도 일어나지 않는다. 데이터가 여러 객체로 나뉘어 있어야 효과가 난다.
ML 학습에서 데이터 입력은 종종 GPU보다 병목이 된다. GPU가 한 배치를 0.1초에 계산하는데 데이터를 읽는 데 0.5초가 걸리면 GPU는 대부분의 시간을 놀게 된다(GPU starvation). Pipe/FastFile mode와 Parquet 같은 효율적 포맷, 적절한 샤딩은 모두 "비싼 GPU를 굶기지 않기" 위한 장치다. 저장 전략이 곧 학습 비용 전략인 이유다.
한 팀이 수 TB의 클릭 로그를 단일 거대 CSV로 S3에 두고 File mode로 학습하다, 매 실험마다 데이터 복사에 40분씩 허비했다. 데이터를 날짜로 파티셔닝한 Parquet 샤드로 재저장하고 Pipe mode로 바꾸자 복사 대기가 사라지고, Athena로 미리 EDA하기도 쉬워졌다. 저장 포맷 하나가 실험 반복 속도를 좌우한 셈이다.