Parquet 포맷을 깊게 이해하고 나서 정리하고 싶었던 Pruning 기법에 대해서 글을 작성하겠습니다.
파케이는 공식문서가 존재하였지만 프루닝 기법에 대해서는 공식문서가 존재하지 않아 여러 문서들을 참고하였습니다.
이전 포스팅 Parquet 내부구조 이해하기 포스팅
Pruning(가지치기) 기법은 CS 여러 분야에서 쓰이지만 제가 정리하고 싶은 데이터 엔지니어링 분야에서는 아래와 같이 정의합니다.
연산 결과에 영향을 주지 않는 데이터를 실행 초기 단계에서 제거하여 불필요한 I/O와 연산을 방지하는 최적화 기법
출처 - gemini
기존의 가지치기, 필터링 등의 개념과 유사하여 생소한 개념은 아니라고 느껴집니다.
다만 엄밀하게 파일 시스템 관점에서 프루닝을 아래와 같이 세 단계로 나눠보았습니다.
1. Column-level: Column Pruning
필요한 컬럼만 선택적으로 읽어오는 기법입니다.
- 원리: Parquet 같은 컬럼형 저장소(Columnar Storage)는 각 컬럼의 데이터가 물리적으로 분리되어 저장됩니다.
- 특징: 쿼리 엔진은 파케이 파일의 스키마를 확인해 해당 컬럼이 위치한 파일 오프셋(Offset)으로 바로 점프합니다. CSV처럼 한 줄(Row) 전체를 읽을 필요가 없으므로 I/O를 가장 확실하게 줄여줍니다.
- 비용: 파케이 포맷 자체의 특성을 이용하므로 추가 비용 없이 자동으로 적용됩니다.
2. Row-level (Horizontal) Pruning: Predicate Pushdown
이 기법은 필터 조건(WHERE)에 따라 불필요한 행의 묶음(Row Group)을 스캔 대상에서 제외합니다.
- 원리: Parquet는 데이터를 'Row Group'이라는 단위로 묶어 저장하는데, 각 그룹 내의 컬럼마다 통계 정보(min/max)가 메타데이터로 기록되어 있습니다.
- 특징: 스캔할 대상이 존재하는지 메타데이터를 확인하여 판단, 대상이 아니라면 해당 그룹에 속한 수만 개의 행을 통째로 건너띕니다(Data Skipping).
- 핵심: 논리적으로는 행을 골라내는 작업이지만, 물리적으로는 컬럼 메타데이터를 활용해 뛰어난 성능을 냅니다.
3. File-level : Partition Pruning
데이터가 저장될 때 특정 기준(주로 날짜 등)에 따라 물리적인 폴더 구조로 나뉘어 있는 경우에 작동합니다.
- 원리: 예를 들어 s3://data/sales/date=2026-02-01/과 같은 구조로 저장되어 있다면, 쿼리 엔진은 WHERE date = '2026-02-01' 조건을 확인하자마자 해당 폴더 외의 모든 경로는 목록조차 불러오지 않습니다.
- 특징: 파일 내부를 열어볼 필요도 없이 파일 시스템의 경로만 보고 판단하므로 비용이 거의 들지 않으며, 가장 많은 파일을 프루닝할 수 있어 가장 영향력이 큰 기법입니다.
그렇다면 프루닝 기법만으로 충분할까요? 이외에 성능을 더 높힐 수 있는 방법은 없을까요?
- 파케이 포맷은 로우 그룹들의 정렬을 보장하지 않습니다.
- 파케이 포맷의 통계정보가 유의미하지 않다면 풀스캔하는 것과 다름 없을 것입니다.
만약 특정 컬럼이 가질 수 있는 값이 1,2,3,4 인데 파케이의 통계 정보가 min=1, max=4라면 프루닝의 의미가 없습니다.
이를 해결하기 위해 각 플랫폼은 데이터 응집도(Locality)를 높이는 테크닉을 제공합니다.
- Databricks: Z-order를 통해 다차원 데이터의 지역성을 보존하며 정렬합니다.
- Google Cloud (BigQuery): Clustering을 통해 특정 컬럼 기준의 블록 정렬을 수행하여 블록 프루닝(Block Pruning) 효율을 극대화합니다.
GCP의 공식문서를 통해 이해해보겠습니다.

- 가장 왼쪽의 테이블은 Not Clustered, Not Partitioned 입니다.즉 해당 테이블은 프루닝 될 수 없고 풀스캔이 발생합니다.
- 중앙의 테이블은 Clustered by country, Not partitioned 입니다. country로 필터조건이 걸린다면 프루닝이 발생합니다.
- 가장 우측의 테이블은 Clusted by country, partitioned by date 입니다.
파티션 프루닝이 날짜로 가능하며, 각 날짜 안에서 블록 프루닝이 되어있습니다.
위 테크닉과 관련된 결론은 아래와 같습니다.
- 해당 테크닉은 물리적 정렬을 수행하는 작업이므로 컴퓨팅 리소스가 발생할 수 있습니다.
- 빅쿼리에서는 클러스터링 설정 자체는 무료지만 내부적으로 데이터를 재정렬하는 '자동 백그라운드 재클러스터링'이 일어납니다.
- 데이터브릭스에서는 z-order 설정 후 OPTIMIZE 명령어를 통해서 실제 데이터의 물리적 재정렬이 발생합니다.
- 적절한 개수의 컬럼으로 지정해야 데이터의 지역성이 보존됩니다.
1개일 때 가장 데이터의 지역성이 클 것이고 지정되는 컬럼이 많아질수록 점차 감소합니다.- Databricks의 z-order 기법(https://en.wikipedia.org/wiki/Z-order)
- 클러스터링 컬럼이 아닌 컬럼으로 쿼리가 된다면 이는 무의미하며 풀스캔과 다를 바 없습니다. 따라서, 사용자 쿼리 패턴 분석이 선행되어야 합니다.
프루닝 기법은 개념 자체가 생소하지 않지만 그렇기 때문에 깊게 파고들어 엄밀하게 구분하기에는 간단하진 않았습니다.
그렇지만 쿼리 성능에 가장 큰 영향을 주기 때문에 한 번은 정리하고 싶었던 개념이었습니다.
Ref.
01. [Docs] https://docs.cloud.google.com/bigquery/docs/clustered-tables?hl=ko#block-pruning
02. [Docs] https://docs.databricks.com/aws/en/delta/data-skipping
'Data Engineering' 카테고리의 다른 글
| Parquet 내부구조 이해하기 (0) | 2026.01.11 |
|---|