pandas Parquet 완벽 가이드 read_parquet to_parquet 엔진 pyarrow fastparquet와 compression 최적화
📌 대용량 데이터를 빠르고 가볍게 다루려면 Parquet와 pandas I O 설정이 정답입니다
데이터를 읽고 쓰는 과정에서 몇 초의 차이가 업무 흐름을 완전히 바꾸곤 합니다.
CSV는 익숙하지만 크기가 커지고 타입 관리가 까다로워 성능이 떨어질 때가 많죠.
그럴 때 칼같이 효율을 뽑아주는 형식이 바로 Parquet입니다.
이 글은 pandas에서 read_parquet과 to_parquet를 어떻게 설정해야 하는지, 그리고 engine으로 선택하는 pyarrow와 fastparquet의 차이, compression 옵션을 실제 작업에 맞게 고르는 법을 한 번에 정리합니다.
복잡한 개념을 피하고, 바로 적용 가능한 체크포인트 위주로 설명해 드릴게요.
프로덕션 파이프라인부터 노트북 실험까지, 동일한 코드를 환경에 맞춰 유연하게 바꾸는 방법이 핵심입니다.
엔진별 성능 특성과 코덱 호환성, 컬럼 단위 읽기 같은 Parquet의 장점을 살리는 설정 포인트를 구체적으로 짚습니다.
또한 타입 손실 없이 데이터를 저장하고 재현하는 전략, 파티셔닝과 인덱스 처리 등 실무에서 자주 부딪히는 이슈를 예제로 풀어냅니다.
필요한 부분만 골라 읽어도 흐름이 끊기지 않도록 섹션을 구성했으니, 원하는 항목부터 바로 이동해 보세요.
📋 목차
🔗 pandas Parquet 입문과 파일 구조
Parquet는 컬럼 지향 압축과 통계 메타데이터를 활용해 I O를 최소화하는 오픈 포맷입니다.
같은 데이터라도 CSV 대비 파일 크기가 작고 특정 컬럼만 읽는 작업이 빠르기 때문에 분석과 파이프라인 모두에서 표준으로 자리잡았습니다.
pandas는 read_parquet과 to_parquet로 Parquet를 다루며, 내부 엔진으로 pyarrow 또는 fastparquet를 사용합니다.
이 섹션에서는 Parquet의 구조와 동작 원리를 이해하고, pandas가 이를 어떻게 활용하는지 기초를 다집니다.
Parquet 파일은 크게 파일 헤더와 푸터, 그리고 하나 이상의 Row Group으로 구성됩니다.
각 Row Group은 여러 컬럼 청크(Column Chunk)를 포함하고, 청크는 다시 Page 단위로 나뉘어 저장됩니다.
푸터에는 스키마, 각 컬럼의 최소·최대값, 널 카운트 같은 통계가 들어 있어 프레디케이트 푸시다운과 컬럼 프루닝이 가능해집니다.
즉, 조건에 맞지 않는 Row Group은 통째로 건너뛰고 필요한 컬럼만 디스크에서 읽기 때문에 처리량이 크게 향상됩니다.
스키마 진화도 장점입니다.
새 컬럼 추가나 타입 변경이 일정 규칙을 지키면 호환될 수 있으며, pandas는 엔진을 통해 스키마를 읽어 적절한 dtype으로 매핑합니다.
범주형이나 타임존 포함 시계열 같은 민감한 타입은 엔진별 직렬화 방식이 달라질 수 있으므로, 팀 내에서 엔진과 타입 규칙을 합의해 두면 재현성이 높아집니다.
- 📁Row Group 크기는 I O 패턴과 메모리에 맞게 설계합니다.
일반적으로 수십 MB 단위가 균형점이 됩니다. - 🧱컬럼 프루닝을 극대화하려면 넓은 테이블에서 자주 쓰지 않는 컬럼은 별도 파일로 분리하는 것도 방법입니다.
- 🧾통계 메타데이터는 필터링 성능의 핵심입니다.
압축과 인코딩을 바꿀 때 통계가 유지되는지 확인합니다.
# 기본 읽기와 쓰기
import pandas as pd
# 쓰기: 엔진과 압축을 명시하면 재현성이 올라갑니다
df.to_parquet("data.parquet", engine="pyarrow", compression="snappy", index=False)
# 읽기: 필요한 컬럼만 선택해 I/O 최소화
cols = ["user_id", "event_time", "amount"]
data = pd.read_parquet("data.parquet", engine="pyarrow", columns=cols)
| 형식 | 특징 요약 |
|---|---|
| CSV | 행 지향 텍스트. 스키마 없음. 대용량에서 느리고 타입 손실 위험. |
| Parquet | 컬럼 지향 바이너리. 스키마와 통계 포함. 컬럼 선택 및 필터링에 유리. |
💡 TIP: 이벤트 로그처럼 날짜로 분할되는 데이터는 폴더 파티셔닝을 이용해 year=YYYY/month=MM/day=DD 구조로 저장하면, 읽을 때 경로 수준에서 조기 필터링이 가능합니다.
⚠️ 주의: 서로 다른 엔진으로 섞어 저장하면 dtype이나 카테고리 인코딩이 달라질 수 있습니다.
프로젝트 내에서는 엔진과 compression을 고정하고, 인덱스 저장 여부도 정책으로 명확히 정하세요.
💬 핵심은 필요한 것만, 가능한 한 적게 읽는 것입니다.
Parquet의 컬럼 지향성, 통계 기반 스킵, 그리고 폴더 파티셔닝을 결합하면 병목을 크게 줄일 수 있습니다.
🛠️ read_parquet 사용법과 columns filters dtype 관리
pandas의 read_parquet 함수는 Parquet 파일을 DataFrame으로 불러오는 표준적인 방법입니다.
필수 인자는 파일 경로와 엔진이며, 그 외에 자주 활용되는 주요 옵션으로 columns, filters, dtype_backend이 있습니다.
이를 적절히 조합하면 대용량 데이터도 빠르게 처리하고, 타입 일관성을 유지하면서 원하는 형태로 불러올 수 있습니다.
🔎 columns 옵션으로 필요한 컬럼만 읽기
Parquet는 컬럼 지향 포맷이라 특정 컬럼만 골라 읽는 것이 가능합니다.
분석에서 필요한 변수만 선택해 불러오면 메모리 사용량과 I O 시간이 크게 줄어듭니다.
import pandas as pd
# 특정 컬럼만 읽기
df = pd.read_parquet(
"events.parquet",
engine="pyarrow",
columns=["user_id", "event_time", "amount"]
)
🧩 filters 인자로 조건 기반 읽기
filters 인자를 사용하면 파일을 전부 읽지 않고 조건에 맞는 데이터만 선택적으로 불러올 수 있습니다.
이는 폴더 파티셔닝과 함께 사용할 때 효과가 극대화됩니다.
# 2025년 1월 데이터만 읽기
df = pd.read_parquet(
"logs/",
engine="pyarrow",
filters=[("year", "=", 2025), ("month", "=", 1)]
)
💡 TIP: filters는 반드시 해당 컬럼이 파티션 키일 때 성능 이점이 큽니다.
단순한 행 단위 조건으로는 효과가 제한적일 수 있습니다.
📐 dtype 관리와 backend 설정
Parquet는 스키마 기반이지만 엔진별 dtype 매핑이 다를 수 있습니다.
특히 nullable integer나 string 타입은 pandas 버전에 따라 변환 결과가 달라질 수 있습니다.
이럴 때 dtype_backend=”numpy_nullable” 또는 “pyarrow” 옵션을 지정해 일관성을 유지할 수 있습니다.
| 옵션 | 설명 |
|---|---|
| dtype_backend=”numpy_nullable” | 기본 pandas 타입에 맞춰 로드. 널 지원 정수 사용 가능. |
| dtype_backend=”pyarrow” | Arrow 기반 컬럼 타입으로 로드. 대규모 데이터프레임에서 성능 유리. |
⚠️ 주의: fastparquet은 일부 dtype에서 pyarrow와 다른 직렬화를 사용할 수 있습니다.
특히 datetime의 timezone 처리에서 차이가 생기므로 혼합 사용은 피하는 것이 좋습니다.
⚙️ to_parquet 옵션과 index partition_cols 저장 전략
데이터를 Parquet 형식으로 저장할 때 사용하는 함수는 to_parquet입니다.
이 함수는 저장 시점에 엔진, 압축, 인덱스 보존 여부, 파티션 컬럼 설정 등 다양한 옵션을 제공합니다.
파일 크기, 로딩 속도, 추후 쿼리 성능에 직접적인 영향을 주기 때문에, 목적에 맞는 옵션을 선택하는 것이 중요합니다.
📌 index 저장 여부
기본적으로 pandas는 DataFrame의 인덱스를 함께 저장합니다.
하지만 대부분의 경우 불필요하게 파일 크기를 늘리므로, index=False로 설정하는 것이 일반적입니다.
특히 단순한 RangeIndex라면 저장하지 않아도 무방합니다.
# 인덱스 제외 저장
df.to_parquet(
"cleaned.parquet",
engine="pyarrow",
index=False,
compression="snappy"
)
📂 partition_cols로 폴더 파티셔닝
Parquet 저장 시 partition_cols 옵션을 지정하면 특정 컬럼 기준으로 디렉터리 구조를 나눠 저장할 수 있습니다.
이 방식은 Spark, Dask, DuckDB 같은 분석 엔진에서 파티션 단위 필터링을 지원하기 때문에 매우 유용합니다.
# 날짜 기준으로 폴더 파티셔닝 저장
df.to_parquet(
"logs/",
engine="pyarrow",
partition_cols=["year", "month"],
index=False,
compression="zstd"
)
💡 TIP: 파티션을 너무 많이 나누면 작은 파일이 폭발적으로 늘어나 성능이 오히려 나빠집니다.
보통 수천 개 이하로 파티션 수를 제한하는 것이 권장됩니다.
🧾 추가 옵션
to_parquet에는 파일 저장 전략을 세밀하게 제어하는 옵션이 있습니다.
예를 들어 row_group_size는 각 Row Group의 크기를 바이트 단위로 조절하여 읽기 성능에 영향을 줍니다.
또한 compression과 함께 compression_level을 지정해 압축 효율과 속도를 최적화할 수 있습니다.
- ⚙️단순한 분석 작업은 index=False로 저장해 용량을 절약하세요.
- 📂날짜·지역·카테고리 등 자주 필터링하는 컬럼은 partition_cols에 지정하세요.
- 🚀대규모 저장 시에는 row_group_size를 조정해 I/O 성능을 튜닝하세요.
⚠️ 주의: 파티셔닝은 강력하지만, 파일 수가 지나치게 많아지면 오히려 관리가 어려워집니다.
클러스터 환경에서는 파일 합치기(compaction) 전략도 함께 고려해야 합니다.
🔌 engine 선택 가이드 pyarrow와 fastparquet
pandas에서 Parquet 파일을 읽고 쓸 때 engine 옵션을 통해 내부 라이브러리를 선택할 수 있습니다.
대표적인 엔진은 pyarrow와 fastparquet입니다.
둘 다 오픈소스이지만 설계 철학과 최적화 방향이 다르기 때문에, 프로젝트 환경과 요구사항에 맞게 선택하는 것이 중요합니다.
⚡ pyarrow
Apache Arrow 프로젝트의 일부로, C++ 기반으로 구현된 고성능 라이브러리입니다.
pandas뿐 아니라 Spark, Dask, DuckDB 등 다양한 데이터 엔진과 호환성이 뛰어나며, 최신 기능 지원이 빠릅니다.
특히 Arrow Datasets, pyarrow.compute 같은 확장 기능을 통해 더 유연하게 활용할 수 있습니다.
🚀 fastparquet
Python에서 구현된 경량 엔진으로, 빠른 설치와 적은 의존성이 장점입니다.
특히 Python-only 환경에서 부담이 적으며, 일부 경우 쓰기 속도에서 pyarrow보다 나은 성능을 보이기도 합니다.
다만 Arrow 프로젝트와의 통합 수준은 pyarrow에 비해 제한적입니다.
| 엔진 | 특징 | 추천 환경 |
|---|---|---|
| pyarrow | C++ 기반, 빠른 성능, Arrow와 긴밀한 호환성 | 대규모 데이터, Spark·Dask 연동 |
| fastparquet | Python 구현, 가벼운 설치, 일부 쓰기 성능 강점 | 소규모 프로젝트, 의존성 최소화 환경 |
# pyarrow 사용
df.to_parquet("dataset_pyarrow.parquet", engine="pyarrow")
# fastparquet 사용
df.to_parquet("dataset_fastparquet.parquet", engine="fastparquet")
- 🔗호환성과 기능 확장이 필요하다면 pyarrow를 선택하세요.
- ⚙️의존성을 최소화하고 설치 속도를 중시한다면 fastparquet가 유리합니다.
⚠️ 주의: 동일한 프로젝트에서 pyarrow와 fastparquet을 섞어 쓰면 dtype 불일치 문제가 발생할 수 있습니다.
한 가지 엔진을 표준으로 정해 사용하는 것이 안전합니다.
💬 엔진 선택은 단순히 코드 실행 문제가 아니라 데이터 생태계와의 호환성까지 고려해야 하는 의사결정입니다.
💡 compression 코덱 비교 snappy gzip zstd brotli
Parquet는 저장 시 compression 코덱을 지정할 수 있습니다.
압축 알고리즘에 따라 파일 크기, 읽기 속도, 쓰기 속도가 달라지기 때문에 데이터 특성과 활용 목적에 맞는 선택이 필요합니다.
대표적으로 많이 쓰이는 옵션은 snappy, gzip, zstd, brotli입니다.
📦 snappy
Google에서 개발한 압축 알고리즘으로, 속도가 매우 빠르고 압축/해제 비용이 적습니다.
파일 크기보다는 읽기/쓰기 성능을 중시할 때 자주 선택합니다.
Spark, Hadoop 생태계에서 기본으로 사용되는 경우가 많습니다.
🌀 gzip
압축률이 높아 저장 공간을 줄이는 데 유리합니다.
다만 압축/해제 속도가 느려서 대규모 분석 파이프라인에서는 병목이 될 수 있습니다.
아카이빙 목적이거나 저장 공간이 절대적으로 중요한 경우 적합합니다.
⚡ zstd
Facebook에서 개발한 알고리즘으로, 빠른 속도와 높은 압축률을 동시에 제공합니다.
최근에는 snappy 대신 zstd를 기본 선택으로 삼는 프로젝트도 많습니다.
압축 레벨을 조정해 속도와 용량의 균형을 맞출 수 있습니다.
🧩 brotli
웹 브라우저용으로 개발된 고압축 알고리즘입니다.
압축률은 가장 높지만 속도가 상대적으로 느립니다.
읽기보다 저장 효율이 중요한 장기 보관용 데이터에 적합합니다.
| 코덱 | 압축률 | 속도 | 추천 용도 |
|---|---|---|---|
| snappy | 낮음 | 매우 빠름 | 실시간 분석, Spark 환경 |
| gzip | 높음 | 느림 | 저장 공간 절약, 아카이브 |
| zstd | 높음 | 빠름 | 균형 잡힌 선택, 최신 환경 |
| brotli | 매우 높음 | 느림 | 장기 보관, 웹 데이터 |
# 다양한 압축 옵션 적용
df.to_parquet("snappy.parquet", engine="pyarrow", compression="snappy")
df.to_parquet("gzip.parquet", engine="pyarrow", compression="gzip")
df.to_parquet("zstd.parquet", engine="pyarrow", compression="zstd", compression_level=5)
df.to_parquet("brotli.parquet", engine="pyarrow", compression="brotli")
- ⚡실시간 분석이나 Spark 워크로드는 snappy가 적합합니다.
- 📦저장 효율을 최우선으로 한다면 gzip 또는 brotli를 고려하세요.
- 🚀속도와 용량의 균형을 원한다면 zstd가 가장 유연한 선택입니다.
⚠️ 주의: 압축 코덱 지원 여부는 엔진과 pandas 버전에 따라 다릅니다.
특정 코덱을 지정하기 전에 pyarrow 또는 fastparquet이 해당 코덱을 지원하는지 확인하세요.
💬 압축 코덱 선택은 단순히 파일 크기를 줄이는 문제가 아니라, 데이터 파이프라인의 속도와 비용까지 좌우하는 중요한 의사결정입니다.
❓ 자주 묻는 질문 (FAQ)
Parquet와 CSV는 어떤 차이가 있나요?
pyarrow와 fastparquet 중 어느 것을 써야 할까요?
to_parquet에서 index를 꼭 저장해야 하나요?
filters 옵션은 언제 효과적인가요?
compression 코덱은 어떤 것을 추천하나요?
Parquet 파일을 여러 개로 저장하는 것이 좋은가요?
dtype 불일치 문제는 어떻게 피할 수 있나요?
Parquet는 모든 데이터에 적합한가요?
📌 pandas Parquet 활용의 핵심 정리
Parquet는 컬럼 지향 저장 포맷으로, 대용량 데이터를 다룰 때 CSV보다 훨씬 효율적인 성능을 보여줍니다.
pandas에서 제공하는 read_parquet과 to_parquet 함수는 엔진과 압축 방식을 적절히 선택할 수 있어, 작업 환경과 목적에 따라 유연하게 최적화할 수 있습니다.
pyarrow는 성능과 호환성이 뛰어나 대규모 프로젝트에 적합하며, fastparquet은 가볍고 설치가 빠른 장점이 있어 소규모 프로젝트에 유용합니다.
또한 snappy, gzip, zstd, brotli 같은 다양한 압축 코덱을 통해 저장 용량과 속도를 균형 있게 조정할 수 있습니다.
실무에서는 index 저장 여부를 상황에 맞게 결정하고, partition_cols를 활용해 파티셔닝 전략을 세우는 것이 중요합니다.
아울러 dtype 호환성을 유지하기 위해 프로젝트 내 엔진과 옵션을 통일하는 습관도 필수적입니다.
결국 pandas Parquet 활용의 핵심은 재현성과 성능 최적화를 동시에 확보하는 데 있습니다.
🏷️ 관련 태그 : pandas, parquet, pyarrow, fastparquet, 데이터엔지니어링, python데이터분석, 압축코덱, 데이터최적화, 대용량데이터, 데이터포맷