본문으로 바로가기
리옵트 핸드북
리옵트 핸드북
DuckDB 고급 활용

시작과 기준선

포지셔닝과 적합한 워크로드버전·설치·런타임 기준연결·스토리지 모델실행 가능한 예제 번들

파일·레이크 분석

CSV·JSON 수집Parquet 레이크 모델링다중 파일·스키마 진화파티션 쓰기와 오브젝트 스토리지Lakehouse 포맷

분석 SQL·연동

Friendly SQL과 매크로시계열·분석 SQL중첩·반정형 데이터Python·Arrow·Polars·BIdbt·MotherDuck·Ibis 생태계Materialization·Index·통계

성능·운영

성능 프로파일링벤치마크·프로파일링 실습메모리·spill·실패 모드동시성·보안·운영보안 Hardening 체크리스트

부록

템플릿참고 자료검증 리포트업데이트 내역
핸드북›DuckDB 고급 활용›Parquet 레이크 모델링

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으로 다시 씁니다.

참고 자료

  • Reading and Writing Parquet Files
  • Parquet Tips
  • Performance Guide: File Formats
  • Indexing and Zonemaps

관련 문서

벤치마크·프로파일링 실습

같은 DuckDB 쿼리를 파일 레이아웃과 세션 설정별로 비교하는 재현 가능한 실습 절차입니다.

실행 가능한 예제 번들

작은 CSV·JSON 샘플과 DuckDB SQL 스크립트로 수집, Parquet 변환, profiling을 직접 실행합니다.

CSV·JSON 수집

CSV 자동 추론, 명시 스키마, JSON 추출과 반정형 데이터 수집의 실전 기준을 정리합니다.

다중 파일·스키마 진화

glob, filename virtual column, union_by_name, 스키마 drift 감지와 파일 manifest 운영 패턴을 다룹니다.

On this page

직접 스캔과 적재의 기준Metadata를 먼저 본다Row group 설계Compression 선택참고 자료