빅데이터와 분산 시스템 — PySpark 관점
50 Python Interview Questions for Data Engineers (2026) — DataCamp (blog) Section 5: Big Data & Distributed Systems (pp.13-14)
이 모듈을 다 읽으면
- PySpark를 표준 Python 대신 선택해야 하는 상황(단일 머신 처리 한계)을 판단할 수 있다
- 파티셔닝과 버킷팅의 목적 차이를 구분할 수 있다
- Parquet의 컬럼형 저장이 컬럼 프루닝과 predicate pushdown이라는 서로 다른 메커니즘으로 성능에 기여하는 방식을 정확히 설명할 수 있다
PySpark 개요, 스타 스키마, 파티셔닝/버킷팅, Parquet의 컬럼형 저장, 데이터 스큐와 솔팅을 Python API 사용자 관점에서 가볍게 다룬다. 원문이 '컬럼 프루닝'과 'predicate pushdown'을 혼동한 부분을 정정한다. Spark 실행 엔진 내부의 셔플·튜닝 세부사항은 batch-processing 카테고리의 Spark 학습 모듈에서 더 깊이 다룬다.
PySpark 개요와 스타 스키마
PySpark는 Apache Spark의 Python API다. 데이터가 너무 커서 한 대의 머신에 담을 수 없을 때 사용한다. PySpark는 데이터와 연산을 클러스터 전체에 분산시켜, 테라바이트 단위의 데이터를 병렬로 처리할 수 있게 해준다.
스타 스키마는 하나의 큰 '팩트(Fact)' 테이블(매출액 같은 정량적 데이터를 담음)이 여러 개의 '디멘션(Dimension)' 테이블(제품명, 날짜 같은 서술적 데이터를 담음)과 연결된 구조다. 쿼리를 빠르고 이해하기 쉽게 만들어주기 때문에 데이터 웨어하우징에서 가장 흔히 쓰이는 모델이다.
핵심 포인트
- PySpark는 단일 머신에 담기지 않는 규모의 데이터를 클러스터에 분산 처리할 때 쓴다.
- 스타 스키마는 팩트 테이블(정량 데이터)과 여러 디멘션 테이블(서술 데이터)로 구성되어 쿼리를 빠르고 단순하게 만든다.
파티셔닝 vs 버킷팅
파티셔닝은 컬럼 값을 기준으로 물리적인 하위 디렉터리를 만든다(예: folder/year=2023/month=01). 이를 통해 쿼리 엔진이 관련 없는 폴더 전체를 건너뛸 수 있다(파티션 프루닝). 버킷팅은 데이터를 고정된 개수의 파일로 해시 분산시켜 한 디렉터리 안에 담는다. 파티셔닝은 굵은 단위의 필터링에, 버킷팅은 세밀한 단위의 조직화와 조인 성능 개선에 쓰인다 — 양쪽이 동일한 키로 동일한 개수의 버킷으로 버킷팅되어 있으면 조인 시 셔플을 줄일 수 있다.
핵심 포인트
- 파티셔닝은 컬럼 값별 물리적 디렉터리를 만들어 쿼리 엔진이 무관한 폴더를 건너뛰게 한다(파티션 프루닝).
- 버킷팅은 고정 개수의 파일로 해시 분산해 세밀한 조직화와 조인 성능(셔플 감소)에 기여한다.
Parquet과 컬럼형 저장 — 정정: 컬럼 프루닝과 predicate pushdown은 다른 개념이다
Parquet은 컬럼형(columnar) 저장 포맷이다. 행 기반인 CSV와 달리, Parquet은 하나의 컬럼에 속한 모든 값을 함께 저장한다.
— 정정: 원문은 이 컬럼형 구조 덕분에 'predicate pushdown(필요한 컬럼만 읽는 것)'이 가능하다고 설명했지만, 이는 두 가지 서로 다른 최적화 개념을 혼동한 것이다. 필요한 컬럼만 읽는 최적화는 '컬럼 프루닝(column pruning)' 또는 '프로젝션 푸시다운(projection pushdown)'이라고 부른다 — 이는 '어떤 컬럼을 읽을 것인가'에 대한 최적화다. 반면 predicate pushdown은 WHERE 절의 필터 조건을 스토리지 레이어까지 내려보내, Parquet 파일 안의 row group별 통계치(최솟값/최댓값)를 이용해 그 필터 조건을 만족할 수 없는 row group을 아예 읽지 않고 건너뛰는 최적화다 — 이는 '어떤 행(row group)을 읽을 것인가'에 대한 최적화로, 컬럼 프루닝과는 별개의 메커니즘이다.
Parquet은 컬럼형 저장 구조 덕분에 이 두 최적화를 모두 지원하며, 둘을 함께 적용하면(필요한 컬럼만, 그리고 조건에 맞는 row group만 읽기) I/O를 크게 줄여 압축률과 더불어 대규모 분석 워크로드를 훨씬 빠르고 저렴하게 만든다.
핵심 포인트
- 컬럼 프루닝(프로젝션 푸시다운)은 '필요한 컬럼만 읽기', predicate pushdown은 'row group 통계로 무관한 행 그룹을 건너뛰기' — 서로 다른 최적화다 — 정정.
- Parquet의 컬럼형 구조는 두 최적화를 모두 지원하며, 함께 적용될 때 I/O 절감 효과가 극대화된다.
- 행 기반 CSV는 이 두 최적화를 근본적으로 지원할 수 없어, 컬럼 지향 분석 워크로드에서 Parquet보다 느리고 비싸다.
데이터 스큐와 솔팅
데이터 스큐는 하나의 파티션이 다른 파티션보다 훨씬 많은 데이터를 가져, 그 파티션을 처리하는 워커 하나가 훨씬 오래 걸리는 현상이다. 조인 키에 무작위 접두사를 붙여 데이터를 더 고르게 분산시키는 '솔팅(Salting)' 기법으로 이 문제를 다룰 수 있다.
보충: Spark 3.x부터는 Adaptive Query Execution(AQE)의 스큐 조인 최적화(spark.sql.adaptive.skewJoin.enabled)가 활성화되어 있으면, 실행 중 수집한 통계를 바탕으로 스큐된 파티션을 자동으로 더 작은 조각으로 분할해 처리해준다. 다만 AQE가 모든 스큐 패턴을 커버하지는 못하므로, 수동 솔팅 기법 자체는 여전히 알아둘 필요가 있다. Spark 클러스터 설정과 셔플 튜닝의 더 깊은 내용은 이 프로그램의 Spark 학습 모듈에서 다룬다.
핵심 포인트
- 데이터 스큐는 특정 파티션에 데이터가 몰려 해당 워커가 병목이 되는 현상이다.
- 솔팅은 조인 키에 무작위 접두사를 붙여 데이터를 고르게 분산시키는 수동 기법이다.
- Spark 3.x의 AQE 스큐 조인 최적화는 런타임 통계로 스큐를 자동 완화해주지만 모든 경우를 커버하지는 않는다 — 보충.