메뉴 닫기

pandas Parquet 완벽 가이드 read_parquet to_parquet 엔진 pyarrow fastparquet와 compression 최적화

pandas Parquet 완벽 가이드 read_parquet to_parquet 엔진 pyarrow fastparquet와 compression 최적화

📌 대용량 데이터를 빠르고 가볍게 다루려면 Parquet와 pandas I O 설정이 정답입니다

데이터를 읽고 쓰는 과정에서 몇 초의 차이가 업무 흐름을 완전히 바꾸곤 합니다.
CSV는 익숙하지만 크기가 커지고 타입 관리가 까다로워 성능이 떨어질 때가 많죠.
그럴 때 칼같이 효율을 뽑아주는 형식이 바로 Parquet입니다.
이 글은 pandas에서 read_parquetto_parquet를 어떻게 설정해야 하는지, 그리고 engine으로 선택하는 pyarrowfastparquet의 차이, compression 옵션을 실제 작업에 맞게 고르는 법을 한 번에 정리합니다.
복잡한 개념을 피하고, 바로 적용 가능한 체크포인트 위주로 설명해 드릴게요.

프로덕션 파이프라인부터 노트북 실험까지, 동일한 코드를 환경에 맞춰 유연하게 바꾸는 방법이 핵심입니다.
엔진별 성능 특성과 코덱 호환성, 컬럼 단위 읽기 같은 Parquet의 장점을 살리는 설정 포인트를 구체적으로 짚습니다.
또한 타입 손실 없이 데이터를 저장하고 재현하는 전략, 파티셔닝과 인덱스 처리 등 실무에서 자주 부딪히는 이슈를 예제로 풀어냅니다.
필요한 부분만 골라 읽어도 흐름이 끊기지 않도록 섹션을 구성했으니, 원하는 항목부터 바로 이동해 보세요.



🔗 pandas Parquet 입문과 파일 구조

Parquet는 컬럼 지향 압축과 통계 메타데이터를 활용해 I O를 최소화하는 오픈 포맷입니다.
같은 데이터라도 CSV 대비 파일 크기가 작고 특정 컬럼만 읽는 작업이 빠르기 때문에 분석과 파이프라인 모두에서 표준으로 자리잡았습니다.
pandas는 read_parquetto_parquet로 Parquet를 다루며, 내부 엔진으로 pyarrow 또는 fastparquet를 사용합니다.
이 섹션에서는 Parquet의 구조와 동작 원리를 이해하고, pandas가 이를 어떻게 활용하는지 기초를 다집니다.

Parquet 파일은 크게 파일 헤더와 푸터, 그리고 하나 이상의 Row Group으로 구성됩니다.
각 Row Group은 여러 컬럼 청크(Column Chunk)를 포함하고, 청크는 다시 Page 단위로 나뉘어 저장됩니다.
푸터에는 스키마, 각 컬럼의 최소·최대값, 널 카운트 같은 통계가 들어 있어 프레디케이트 푸시다운컬럼 프루닝이 가능해집니다.
즉, 조건에 맞지 않는 Row Group은 통째로 건너뛰고 필요한 컬럼만 디스크에서 읽기 때문에 처리량이 크게 향상됩니다.

스키마 진화도 장점입니다.
새 컬럼 추가나 타입 변경이 일정 규칙을 지키면 호환될 수 있으며, pandas는 엔진을 통해 스키마를 읽어 적절한 dtype으로 매핑합니다.
범주형이나 타임존 포함 시계열 같은 민감한 타입은 엔진별 직렬화 방식이 달라질 수 있으므로, 팀 내에서 엔진과 타입 규칙을 합의해 두면 재현성이 높아집니다.

  • 📁Row Group 크기는 I O 패턴과 메모리에 맞게 설계합니다.
    일반적으로 수십 MB 단위가 균형점이 됩니다.
  • 🧱컬럼 프루닝을 극대화하려면 넓은 테이블에서 자주 쓰지 않는 컬럼은 별도 파일로 분리하는 것도 방법입니다.
  • 🧾통계 메타데이터는 필터링 성능의 핵심입니다.
    압축과 인코딩을 바꿀 때 통계가 유지되는지 확인합니다.
CODE BLOCK
# 기본 읽기와 쓰기
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 시간이 크게 줄어듭니다.

CODE BLOCK
import pandas as pd

# 특정 컬럼만 읽기
df = pd.read_parquet(
    "events.parquet",
    engine="pyarrow",
    columns=["user_id", "event_time", "amount"]
)

🧩 filters 인자로 조건 기반 읽기

filters 인자를 사용하면 파일을 전부 읽지 않고 조건에 맞는 데이터만 선택적으로 불러올 수 있습니다.
이는 폴더 파티셔닝과 함께 사용할 때 효과가 극대화됩니다.

CODE BLOCK
# 2025년 1월 데이터만 읽기
df = pd.read_parquet(
    "logs/",
    engine="pyarrow",
    filters=[("year", "=", 2025), ("month", "=", 1)]
)

💡 TIP: filters는 반드시 해당 컬럼이 파티션 키일 때 성능 이점이 큽니다.
단순한 행 단위 조건으로는 효과가 제한적일 수 있습니다.

📐 dtype 관리와 backend 설정

Parquet는 스키마 기반이지만 엔진별 dtype 매핑이 다를 수 있습니다.
특히 nullable integerstring 타입은 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라면 저장하지 않아도 무방합니다.

CODE BLOCK
# 인덱스 제외 저장
df.to_parquet(
    "cleaned.parquet",
    engine="pyarrow",
    index=False,
    compression="snappy"
)

📂 partition_cols로 폴더 파티셔닝

Parquet 저장 시 partition_cols 옵션을 지정하면 특정 컬럼 기준으로 디렉터리 구조를 나눠 저장할 수 있습니다.
이 방식은 Spark, Dask, DuckDB 같은 분석 엔진에서 파티션 단위 필터링을 지원하기 때문에 매우 유용합니다.

CODE BLOCK
# 날짜 기준으로 폴더 파티셔닝 저장
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 옵션을 통해 내부 라이브러리를 선택할 수 있습니다.
대표적인 엔진은 pyarrowfastparquet입니다.
둘 다 오픈소스이지만 설계 철학과 최적화 방향이 다르기 때문에, 프로젝트 환경과 요구사항에 맞게 선택하는 것이 중요합니다.

⚡ 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 구현, 가벼운 설치, 일부 쓰기 성능 강점 소규모 프로젝트, 의존성 최소화 환경
CODE BLOCK
# 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 매우 높음 느림 장기 보관, 웹 데이터
CODE BLOCK
# 다양한 압축 옵션 적용
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는 어떤 차이가 있나요?
Parquet는 컬럼 지향 바이너리 포맷으로, 특정 컬럼만 읽을 수 있고 압축 효율이 뛰어납니다. 반면 CSV는 행 지향 텍스트 포맷으로 단순하지만 대용량에서 속도가 느리고 타입 정보가 보존되지 않습니다.
pyarrow와 fastparquet 중 어느 것을 써야 할까요?
pyarrow는 C++ 기반으로 빠르고 기능 지원이 광범위합니다. fastparquet은 Python 기반으로 설치가 가볍고 일부 상황에서 쓰기 속도가 빠릅니다. 대규모 프로젝트라면 pyarrow, 작은 프로젝트라면 fastparquet을 고려하세요.
to_parquet에서 index를 꼭 저장해야 하나요?
대부분의 경우 index는 필요하지 않아 index=False로 설정하는 것이 일반적입니다. 단, MultiIndex 같은 특별한 인덱스를 보존하려면 저장하는 편이 안전합니다.
filters 옵션은 언제 효과적인가요?
filters는 해당 컬럼이 파티션 키일 때 가장 효과적입니다. 단순한 조건식에는 성능 차이가 거의 없을 수 있습니다.
compression 코덱은 어떤 것을 추천하나요?
실시간 분석 환경은 snappy, 저장 공간 절약이 중요하다면 gzip이나 brotli, 균형 잡힌 성능을 원한다면 zstd를 권장합니다.
Parquet 파일을 여러 개로 저장하는 것이 좋은가요?
파티션 단위로 나누는 것은 좋지만, 지나치게 작은 파일이 많아지면 관리와 성능에 문제가 생깁니다. 적정한 Row Group과 파티션 수를 유지하는 것이 중요합니다.
dtype 불일치 문제는 어떻게 피할 수 있나요?
한 프로젝트에서 엔진을 통일하고, dtype_backend 옵션을 명시하는 것이 가장 확실한 방법입니다. 특히 datetime과 categorical 타입에서 차이가 많이 납니다.
Parquet는 모든 데이터에 적합한가요?
대부분의 테이블형 데이터에 적합하지만, 이미지, 비디오 같은 비정형 데이터에는 맞지 않습니다. 이런 경우에는 별도의 포맷과 함께 메타데이터만 Parquet로 관리하는 방식이 유용합니다.

📌 pandas Parquet 활용의 핵심 정리

Parquet는 컬럼 지향 저장 포맷으로, 대용량 데이터를 다룰 때 CSV보다 훨씬 효율적인 성능을 보여줍니다.
pandas에서 제공하는 read_parquetto_parquet 함수는 엔진과 압축 방식을 적절히 선택할 수 있어, 작업 환경과 목적에 따라 유연하게 최적화할 수 있습니다.
pyarrow는 성능과 호환성이 뛰어나 대규모 프로젝트에 적합하며, fastparquet은 가볍고 설치가 빠른 장점이 있어 소규모 프로젝트에 유용합니다.
또한 snappy, gzip, zstd, brotli 같은 다양한 압축 코덱을 통해 저장 용량과 속도를 균형 있게 조정할 수 있습니다.

실무에서는 index 저장 여부를 상황에 맞게 결정하고, partition_cols를 활용해 파티셔닝 전략을 세우는 것이 중요합니다.
아울러 dtype 호환성을 유지하기 위해 프로젝트 내 엔진과 옵션을 통일하는 습관도 필수적입니다.
결국 pandas Parquet 활용의 핵심은 재현성성능 최적화를 동시에 확보하는 데 있습니다.


🏷️ 관련 태그 : pandas, parquet, pyarrow, fastparquet, 데이터엔지니어링, python데이터분석, 압축코덱, 데이터최적화, 대용량데이터, 데이터포맷