Apache Parquet
Apache Parquet은 컬럼 지향(Columnar) 저장 형식임.
대규모 분산 처리 환경(Hadoop, Spark 등)에서 효율적으로 데이터 분석을 수행하기 위한 오픈소스 파일 포맷임.
빠른 쿼리 성능, 높은 압축률, 유연한 스키마 정의 등 다양한 이점을 제공하여 빅데이터 생태계에서 사실상 표준으로 자리 잡음.
Apache Parquet 특징과 철학
1. 컬럼 지향 저장 방식(Columnar Format)
Parquet은 같은 컬럼(열)의 데이터를 인접하게 저장하여, 열 단위로 효율적으로 읽고 쓸 수 있도록 함.
예를 들어 “age”, “gender”, “income” 등의 컬럼이 있을 때, 행(row) 단위 포맷(CSV, JSON)에서는 레코드 1행, 2행, 3행 순으로 데이터를 연속 저장하지만, Parquet에서는 “age”만 연속으로, “gender”만 연속으로 저장함.
컬럼 지향 구조로 인해 필요한 열만 Select해서 읽는 쿼리 최적화(Projection Pruning)가 가능하고, 압축 효율도 높음.
2. 효율적인 압축(Compression) 및 인코딩(Encoding)
컬럼 단위로 같은 유형의 데이터가 연속되어 있기 때문에, 높은 압축률을 기대할 수 있음.
예를 들면, Dictionary Encoding, Run-length Encoding 등
컬럼별로 맞춤형 압축 알고리즘(ZSTD, Snappy, GZIP 등)을 선택할 수 있고, Nested Column 구조를 가진 경우에도 하위 필드별로 독립적으로 압축할 수 있음.
3. 대규모 분산 처리 환경에 최적화
Hadoop Distributed File System(HDFS) 뿐 아니라, Amazon S3, Google Cloud Storage 등 객체 스토리지에서도 효율적으로 동작함.
Spark, Hive, Presto(Trino), Dremio, Impala 등 다양한 쿼리 엔진에서 Parquet을 기본 스토리지 포맷으로 지원함.
4. 스키마 정보 내장(Self-describing)
Parquet 파일 자체에 스키마(메타데이터)가 포함되어 있어, 별도로 스키마 정의를 제공하지 않아도 됨.
Nested 구조(Struct, List, Map 등)를 표현할 수 있어, 복잡한 데이터 모델에 대해서도 효율적인 쿼리를 제공함.
내부 구조 (Parquet File Layout)
+----------------------+
| File Footer |
| (metadata, schema, |
| column statistics, |
| column metadata etc)|
+----------------------+
| Row Groups | --> 여러 개
| +------------------+|
| | Column Chunks | --> 컬럼별 데이터
| | +--------------+|
| | | Pages || --> 실제 데이터(압축 & 인코딩 적용)
| | +--------------+|
| +------------------+|
+----------------------+
1. Row Group
Parquet은 테이블 데이터를 Row Group이라는 단위로 나누어 저장함.
하나의 Row Group에는 일정 범위(예: 128MB 등)에 해당하는 행들이 들어가며, 분산 처리 시 Row Group 단위로 병렬 처리가 가능함.
2. Column Chunk
Row Group 내에서 각 컬럼별로 Column Chunk가 존재함.
예: Row Group 1에는 “age” Column Chunk, “gender” Column Chunk, “income” Column Chunk가 각각 저장됨.
3. Page
Column Chunk는 여러 개의 Page로 구성되며, 실제 데이터와 인코딩/압축 정보 등이 저장됨.
Page 단위로 압축을 적용하고, Page 헤더에 통계(statistics) 정보를 담아서 필터링(Pruning)에 활용할 수 있음.
4. Footer(메타데이터)
Parquet 파일의 끝 부분(Footer)에 파일 전체에 대한 메타데이터(스키마, Row Group/Column Chunk 위치, 통계 정보 등)가 저장됨.
쿼리 엔진은 이 메타데이터를 빠르게 읽어, 필요한 컬럼이나 Row Group만 선택적으로 읽게 됨(Predicate Pushdown 최적화).
성능 최적화 기법
1. 컬럼 단위 Predicate Pushdown
Parquet 메타데이터(파일 Footer, Page Header 등)에 담긴 최소/최대 값, Null Count 등 통계 정보를 활용하면, 쿼리 조건이 맞지 않는 Row Group이나 Page를 아예 읽지 않을 수 있음.
예를 들어, age > 30 필터가 걸린 쿼리 시, Row Group의 age 컬럼 최대값이 25라면 이 Row Group은 스캔할 필요가 없음.
2. 사전 인코딩(Dictionary Encoding)
고유값이 제한적인 열(예: 국가, 성별 등)에 대해 사전(Dictionary)을 만들어, 실제 데이터 대신 사전 인덱스만 저장할 수 있음.
데이터 압축 효율이 극대화되고, 메모리 사용량과 I/O를 크게 줄여줌.
3. 압축 알고리즘 선택
Parquet은 Snappy, ZSTD, GZIP 등 다양한 알고리즘을 지원함.
데이터 특성(텍스트, 숫자, 중복도 등)에 따라 적절한 알고리즘을 선택할 수 있음.
Snappy/ZSTD는 압축 속도가 빠르고 상대적으로 덜 압축되며, GZIP은 더 높은 압축률을 제공하지만 CPU 부담이 클 수 있음.
4. 적절한 Row Group 크기
일반적으로 Row Group은 128MB ~ 512MB 사이로 설정하는 것이 권장됨(사용하는 엔진/워크로드에 따라 최적값이 다를 수 있음).
Row Group이 너무 작으면(예: 1MB) 메타데이터가 많아져서 I/O 오버헤드가 커지고, 너무 크면 한 번에 읽어야 하는 데이터가 많아서 효율이 떨어질 수 있음.
5. 파일 사이즈 관리
많은 작은 파일(Small Files)이 존재하면 메타데이터 관리 비용이 급격히 증가하고, 쿼리 성능이 저하됨.
Spark/Hive 등에서 파일 병합(Compaction) 작업을 통해 적절한 사이즈로 유지하는 것이 좋음.
Parquet 스키마 구조
1. Primitive Type vs. Logical Type
Parquet은 내부적으로 INT32, INT64, BYTE_ARRAY 등 원시 타입(Primitive type)을 사용함.
이를 확장해 DATE, DECIMAL, TIMESTAMP, UUID 등 논리 타입(Logical type)으로 해석할 수 있음.
2. Nested Type 지원
Parquet은 Repetition Level, Definition Level을 통해 Nested Column 구조(Struct, List, Map)를 표현함.
Spark, Hive 등 엔진과 연동 시, 내부적으로 이 레벨 정보를 해석하여 중첩 필드를 쿼리할 수 있음.
3. Schema Evolution
Parquet 파일에 컬럼이 추가되거나 삭제되어도(Forward/Backward Compatibility) 어느 정도 호환성을 유지할 수 있음.
컬럼 추가 시에는 기존 파일에 없는 컬럼에 대해 Null 처리 등을 적용하고, 컬럼 삭제 시에는 해당 컬럼을 무시함.
Parquet을 활용한 워크플로우 및 모범 사례
1. 데이터 레이크(Lake) 및 데이터 웨어하우스(Analytics) 활용
AWS S3, Azure Blob, GCP GCS 등의 객체 스토리지 위에 Parquet 파일을 저장하고, Spark SQL, Trino(Presto), Athena, BigQuery 등으로 쿼리하는 아키텍처가 널리 쓰임.
ETL/ELT 파이프라인에서 Raw → Parquet 변환을 통해 분석, 머신러닝, 리포팅 등에 최적화된 포맷을 유지함.
2. Partitioning(분할) 전략
폴더 구조 상에서 날짜, 지역, 카테고리 등을 기준으로 물리적 디렉터리 분할을 수행함.
예를 들어, s3://bucket/events/dt=2024-01-01/ 형태로 파티션을 나눠 두면, 쿼리 시 특정 날짜만 읽음으로써 스캔 범위를 대폭 줄일 수 있음.
3. Schema-on-read 모델
Parquet 파일에는 자체 스키마가 존재하지만, 분석 엔진은 별도로 테이블 정의(DDL)를 통해 외부 테이블(External Table) 형태로 파일을 읽어옴.
스키마 진화(컬럼 추가/삭제)가 잦아도, Parquet 파일과 분석 엔진 간에 자유롭게 호환이 가능함.
4. Compaction & Optimize
많은 소규모 Parquet 파일이 생성되면, Spark나 Hive의 INSERT OVERWRITE, OPTIMIZE(Delta Lake 등) 등을 통해 주기적으로 병합(Compaction) 작업을 수행하여 적절한 파일 사이즈를 유지함.
병합 작업 후에는 Parquet 파일이 정리되어 메타데이터 부담이 줄고 쿼리 성능이 향상됨.
5. 데이터 카탈로그 & 메타스토어
Hive Metastore, Glue Data Catalog, Unity Catalog(Snowflake & Databricks) 등으로 Parquet 파일 위치와 스키마 정보를 관리하면, 통합된 환경에서 손쉽게 접근할 수 있음.
주의 사항 및 한계
1. 실시간 업데이트/삭점 작업에 대한 부담
Parquet은 Append/Batch 중심의 워크로드에 최적화되어 있으므로, Row 단위의 잦은 Update/Delete가 필요한 온라인 트랜잭션 처리(OLTP) 시나리오에는 적합하지 않음.
이를 보완하기 위해 Apache Hudi, Delta Lake, Iceberg 등과 같은 테이블 포맷이 등장해, ACID 세맨틱과 Incremental Update를 지원함.
2. 소규모 쿼리 성능
소량 데이터(예: 몇 MB 수준)에 대한 쿼리는 오히려 CSV나 JSON만큼 빠르지 않을 수 있음.
대용량을 분석할 때 Parquet의 이점이 극대화됨.
3. 압축/인코딩 오버헤드
압축률과 해제(decompression) 속도 간 트레이드오프가 존재함.
CPU 자원이 제한적이면 GZIP과 같은 높은 압축률 알고리즘으로 인해 처리 시간이 길어질 수 있음.
4. 파일 호환성 이슈
Parquet 스펙 자체는 오픈 표준이지만, 각 엔진별 Parquet Writer 버그나 Logical Type 해석 차이로 인해 호환성 문제가 발생하기도 함.
최신 Spark/Arrow 라이브러리 등에서 주로 해결되었으나, 간헐적으로 문제가 발생할 수 있으므로 테스트 환경에서 충분히 검증해야 함.
정리
Apache Parquet은 빅데이터 분석 영역에서 사실상 표준에 가까운 위치를 차지하는 컬럼 지향 파일 형식임.
1. 컬럼 단위 저장과 압축을 통한 고효율 I/O
2. 메타데이터를 활용한 Predicate Pushdown 및 Projection Pruning
3. Nested Schema 지원과 배치 처리(ETL/ELT) 중심 워크로드에 최적화된 구조
이러한 강점을 통해 Spark, Hive, Presto(Trino), Impala, Athena 등 다양한 엔진에서 뛰어난 쿼리 성능을 발휘함.
단점으로는 자주 변하는 데이터(실시간 Update/Delete)를 처리하는 데 적합하지 않지만, Hudi·Delta·Iceberg 등 신세대 테이블 포맷과 결합하여 이 문제를 해결할 수 있음.
정리하자면, Parquet은 대규모 데이터 분석 및 머신러닝 워크로드에서 저장 비용을 절감하고, 쿼리 성능을 높이는 핵심 포맷임.
전체 분석 파이프라인에서 Parquet을 어떻게 활용하고, 어떤 파티셔닝·파일 크기·압축 방식·스키마 진화 전략을 취할지 설계하는 것은 빅데이터 아키텍트에게 매우 중요한 과제임.
'Programming Language > Python' 카테고리의 다른 글
[Python] 특정 기간동안 일 단위 날짜 함수 (0) | 2025.01.04 |
---|---|
[Python] Avro 파일 개념 (0) | 2025.01.04 |
[Python] 너비 우선 탐색 (0) | 2024.06.09 |
[Python] 파이썬에서 사용할 수 있는 저수준, 고수준 API (0) | 2024.05.25 |
[Python] 저수준 API와 고수준 API에 대해서 (0) | 2024.05.25 |