Parquet 레이크 모델링
Parquet 직접 스캔, metadata 함수, row group, compression, materialization 기준을 정리합니다.
핵심 요약
- DuckDB는 Parquet를 column projection·filter pushdown으로 직접 읽습니다. 다만 반복 쿼리나 join이 많을 때는 매번 decompression을 다시 하고 통계도 부족해서 DuckDB 테이블에 적재하는 편이 낫습니다.
- 성능 문제는 SQL보다 파일 구조에서 비롯될 때가 많으니, parquet_schema·parquet_metadata로 파일 수, row group, compression, statistics를 먼저 봅니다.
- row group 수는 그 파일을 읽는 CPU thread 수 이상으로 잡습니다. 너무 작으면 metadata overhead가 커지고, 너무 크면 selective query와 병렬성이 약해집니다.
- 자주 필터링하는 날짜·계정·tenant 컬럼으로 ORDER BY 정렬해 zonemap 효율을 높입니다.
- compression은 기본 snappy, 저장 비용이 중요하면 zstd를 쓰고, 해제 비용이 큰 gzip은 피합니다. 같은 파일을 반복해서 직접 스캔한다면 무거운 compression이 오히려 불리합니다.
DuckDB와 Parquet는 함께 쓸 때 가치가 큽니다. DuckDB는 Parquet를 직접 읽으면서 column projection과 filter pushdown을 활용하고, metadata 함수로 파일 구조를 들여다봅니다. 하지만 모든 Parquet를 직접 스캔하는 것이 정답은 아닙니다.
직접 스캔과 적재의 기준
| 기준 | Parquet 직접 스캔 | DuckDB 테이블 적재 |
|---|---|---|
| 1회성 탐색 | 적합 | 과함 |
| 반복 쿼리 | 가능하지만 매번 decompression | 유리 |
| 많은 join | 통계가 부족할 수 있음 | cardinality estimate가 유리 |
| 디스크 여유 | 원본만 필요 | DB 파일만큼 추가 공간 필요 |
| 데이터 공유 | 파일 lake와 잘 맞음 | 단일 DB 파일 배포에 유리 |
-- 직접 스캔
SELECT region, sum(amount) AS revenue
FROM 's3://lake/orders/year=2026/month=*/part-*.parquet'
WHERE order_date >= DATE '2026-01-01'
GROUP BY ALL;
-- 반복 분석용 적재
CREATE OR REPLACE TABLE orders AS
SELECT *
FROM read_parquet('s3://lake/orders/**/*.parquet', hive_partitioning = true);Metadata를 먼저 본다
SELECT *
FROM parquet_schema('curated/orders.parquet');
SELECT
file_name,
row_group_id,
row_group_num_rows,
compression
FROM parquet_metadata('curated/orders.parquet');Parquet 성능 문제는 SQL보다 파일 구조에서 비롯될 때가 많습니다. 파일 수, row group 수, compression, column type, min/max statistics가 필터 pushdown과 병렬성을 좌우합니다.
Row group 설계
DuckDB 문서는 Parquet row group size 기본값과 병렬성의 관계를 설명합니다. 한 파일 안의 row group 수를 그 파일을 읽는 CPU thread 수 이상으로 잡는 것이 좋은 기준입니다. row group이 너무 작으면 metadata overhead가 커지고, 너무 크면 selective query와 병렬성이 약해집니다.
COPY (
SELECT *
FROM orders
ORDER BY order_date, customer_id
) TO 'curated/orders.parquet'
(FORMAT parquet, COMPRESSION zstd, ROW_GROUP_SIZE 100000);정렬은 zonemap 효율을 높입니다. 날짜, 계정, tenant처럼 자주 필터링하는 컬럼이 있다면 output을 만들 때 정렬 순서를 의도적으로 잡아 둡니다.
Compression 선택
| 방식 | 특징 | 권장 |
|---|---|---|
| snappy | 빠른 압축/해제, 넓은 호환성 | 기본 운영 |
| zstd | 압축률과 속도의 균형 | 저장 비용이 중요할 때 |
| gzip | 해제 비용이 큼 | 기존 파일 호환 외에는 피함 |
DuckDB performance guide는 무거운 compression이 반복 직접 스캔에서 불리할 수 있다고 설명합니다. 같은 파일을 거듭 분석한다면 DuckDB 테이블로 적재하거나 가벼운 compression으로 다시 씁니다.