홈으로 돌아가기

DuckDB를 저장소로 사용: ETL Postgres 대체

DuckDB는 하나의 파일에 컴팩트한 분석 저장소를 구현하여 OLAP 작업을 위한 ETL + Postgres를 대체합니다. 아키텍처, 업데이트 스크립트, SLA 및 제한사항 설명. Parquet 데이터 제품 분석을 위한 개발자에게 적합.

DuckDB: ETL 혼란 대신 마이크로 저장소
Advertisement 728x90

DuckDB로 구현하는 컴팩트 분석 데이터 웨어하우스: ETL과 Postgres 버리기

DuckDB는 단일 .duckdb 파일로 분석 데이터 웨어하우스를 구축할 수 있게 해주며, OLAP 워크로드에서 ETL 파이프라인과 Postgres를 생략할 수 있습니다. 이 엔진은 로컬 파일이나 S3/GCS에서 Parquet, CSV, JSON을 직접 처리해 분산 인프라 없이 대시보드와 리포트에 빠른 데이터 액세스를 제공합니다. 자원이 제한된 팀에서 데이터 신선도와 재현성을 최우선으로 할 때 딱 맞습니다.

전통적인 ETL + Postgres 스택의 고통스러운 문제점

Postgres는 OLTP 워크로드를 잘 처리하지만, OLAP 쿼리는 연쇄적인 문제를 일으킵니다: 인덱스가 vacuuming을 늦추고, 집계가 트랜잭션과 경쟁하며, ETL 작업이 스키마 변경과 얽힙니다. 팀들은 분석보다 관리 작업에 더 많은 시간을 쏟게 됩니다. DuckDB는 영속 스토리지 없는 임베디드 OLAP 엔진으로 이러한 실패 지점을 제거합니다.

아키텍처는 간단해집니다:

Google AdInline article slot
  • 소스(DB, S3, CSV) → Parquet 스냅샷 → DuckDB (bronze/silver/gold 레이어) → BI 내보내기.

파이프라인은 뷰와 내보내기를 포함한 스케줄링된 스크립트로 축소되어 운영 오버헤드를 최소화합니다.

DuckDB 마이크로 웨어하우스의 SLA

클러스터 복잡성 없이 명확한 SLA를 제공할 수 있습니다:

  • 데이터 신선도: 타임스탬프 로깅으로 15~60분마다 업데이트.
  • 정확성: 코드 리뷰가 적용된 버전 관리 SQL 뷰의 메트릭.
  • 성능: 90일 데이터 대시보드에서 p95 < 2초.
  • 복구: Parquet에서 30분 이내 완전 재구축.
  • 운영/비용: 하나의 파일 + 하나의 작업, 실행 스토리지 비용 없음.

.duckdb 파일은 백업과 이동이 쉽습니다.

Google AdInline article slot

제품 분석 사용 사례

관계형 DB에 이벤트가 있고 S3에 로그가 있는 B2B SaaS의 경우:

  • 테이블의 일일 스냅샷을 파티셔닝된 Parquet으로.
  • 이벤트를 날짜 파티션 Parquet 파일로.
  • Gold 레이어 메트릭 뷰 (WAU, 유지 코호트).
  • BI 도구용 큐레이션된 Parquet 내보내기.

httpfs 확장은 로컬 복사 없이 S3 직접 읽기를 가능하게 합니다. DuckDB는 여러 Parquet 파일을 단일 테이블처럼 집계합니다.

실전 구현 스크립트

업데이트 스크립트 (Python)

import duckdb
from datetime import datetime

DB = "micro_warehouse.duckdb"

con = duckdb.connect(DB)
con.execute("INSTALL httpfs;")
con.execute("LOAD httpfs;")

con.execute("""
CREATE OR REPLACE VIEW bronze_events AS
SELECT *
FROM read_parquet('data/events/date=*/events-*.parquet');
""")

con.execute("""
CREATE OR REPLACE VIEW silver_events AS
SELECT
  CAST(event_time AS TIMESTAMP) AS event_time,
  user_id,
  team_id,
  event_name,
  NULLIF(properties, '') AS properties
FROM bronze_events
WHERE user_id IS NOT NULL;
""")

con.execute("""
CREATE OR REPLACE VIEW gold_weekly_active_teams AS
SELECT
  date_trunc('week', event_time) AS week,
  COUNT(DISTINCT team_id) AS weekly_active_teams
FROM silver_events
GROUP BY 1
ORDER BY 1;
""")

con.execute("""
COPY (SELECT * FROM gold_weekly_active_teams)
TO 'exports/gold_weekly_active_teams.parquet' (FORMAT PARQUET);
""")

con.execute("CREATE OR REPLACE TABLE ops_refresh_log AS SELECT 1 AS dummy;")
con.execute("""
INSERT INTO ops_refresh_log
SELECT 1
""")

print("Update OK:", datetime.utcnow().isoformat(), "DB:", DB)

이 스크립트는 bronze/silver/gold 레이어를 구축하고 메트릭을 내보냅니다.

Google AdInline article slot

증분 업데이트

업서트를 위해 키(week, team_id)로 MERGE를 사용해 물리화 테이블에 적용하고, 슬라이딩 윈도우를 재계산합니다.

제로 다운타임 마이그레이션

Postgres에 OLTP를 유지하고, postgres_scanner 확장을 통해 라이브 인스턴스에 읽기/쓰기 액세스로 OLAP를 DuckDB로 마이그레이션합니다. 리팩토링 없이 쿼리를 점진적으로 마이그레이션합니다.

웨어하우스로서 DuckDB의 한계

적합한 경우:

  • 소수 분석가 (대시보드, 내보내기).
  • 추가 전용 또는 스냅샷 데이터.
  • 휴대 가능한 Parquet 워크플로.

부적합한 경우:

  • 대규모 동시 사용자 인터랙티브.
  • ACID 보장 OLTP 쓰기.
  • 다중 테넌트 행 수준 보안.
  • 다수 프로듀서의 엔터프라이즈 데이터 계약.

주요 요약

  • DuckDB는 Parquet/S3를 직접 읽는 단일 파일 임베디드 OLAP 엔진.
  • 스택 단순화: ETL + Postgres 대신 스크립트 + 뷰.
  • 달성 가능한 SLA: 15분 신선도, p95<2초, 30분 미만 복구.
  • postgres_scanner로 점진적 마이그레이션.
  • 한계: 낮은 동시성, OLTP 부적합.

— Editorial Team

Advertisement 728x90

다음 읽기