The small-file problem gets worse with CDC

Source: streambed.dev/blog | Published: 2026-08-30


한 줄 요약

CDC는 “작은 배치 → 커밋”의 반복이라 커밋당 메타데이터 비용이 지배적인데, DuckDB가 이미 쿼리 엔진이라면 카탈로그 메타데이터를 오브젝트 스토어 파일이 아니라 DB에 두는 DuckLake가 Iceberg COW보다 이 모양에 훨씬 잘 맞는다.

핵심 주장/내용

  • small-file 문제는 레이크하우스에서 잘 알려져 있지만 CDC 워크로드에서 더 나빠진다: 레이크하우스 테이블로의 모든 flush에는 비용이 있다 — 더 많은 파일, 더 많은 메타데이터, 더 많은 커밋 작업. update와 delete가 그것을 더 나쁘게 만들고, 특히 copy-on-write에서 그렇다
  • CDC는 좀처럼 하나의 크고 깔끔한 배치가 아니다 — 보통 작은 변경의 꾸준한 스트림이다 (small batch → commit 반복). 작은 커밋은 freshness에 좋고, 커밋마다 레이크 메타데이터를 많이 만들 때 나쁘다
    • Iceberg에서 작은 커밋은 더 많은 data file, manifest, metadata file, snapshot을 뜻할 수 있다. update/delete에서는 copy-on-write가 옛 파일을 읽고, 바뀐 행을 제거하고, 새 파일을 쓰는 것을 의미할 수도 있다. 이 작업이 빠르게 누적된다
  • 좁은 경로가 다른 답을 만든다: Streambed는 성숙하고 널리 지원되며 여러 엔진에 걸친 오픈 테이블 포맷을 원할 때 좋은 선택인 Iceberg로 시작했다. 하지만 Streambed의 경로는 좁다 — Postgres WAL → Streambed → DuckDB query server. 그래서 질문이 단순해졌다: “DuckDB가 이미 쿼리 엔진이라면, 작고 반복적인 CDC flush에 Iceberg가 여전히 최선의 기본 타깃인가?”
  • DuckLake가 맞는 이유는 카탈로그의 위치: DuckLake도 테이블 데이터는 여전히 Parquet으로 저장한다. 차이는 카탈로그 메타데이터가 어디 사는가다. 모든 테이블 메타데이터를 오브젝트 스토어 파일로 저장하는 대신 DuckDB·SQLite·Postgres 같은 데이터베이스에 카탈로그 메타데이터를 유지한다
    • Streambed에게 이것이 중요한 이유는 DuckDB가 이미 hot path에 있기 때문이다 → Postgres changes → DuckDB/DuckLake writer → DuckDB query server
    • 마법이 아니다. 데이터는 여전히 써야 한다. 하지만 커밋 경로가 CDC의 모양에 더 잘 맞는다
  • Iceberg는 사라지지 않는다: Spark·Trino·Snowflake·Flink 등 엔진 간 광범위한 레이크하우스 상호운용성이 필요하면 여전히 유용하다. 하지만 Streambed의 목표는 “Postgres 데이터를 DuckDB 기반 분석 레플리카로 제공하되 Postgres 클라이언트·쿼리 호환성을 최대한 보존” 이고, 테이블 포맷은 대체로 배경에 머물러야 한다. 사용자는 Postgres 데이터가 신선하고 쿼리 가능하고 연결하기 쉽다는 것만 신경 쓰면 된다
    • 다음 큰 작업은 Postgres 대면 레이어 — Postgres 클라이언트, SQL 호환성, 함수·연산자, information_schema·pg_catalog, prepared statement·파라미터, JSON·배열·UUID·numeric·bytea·timestamp·time zone·TOAST 무거운 컬럼의 타입 충실도

주요 수치 / 사실

  • 벤치마크 구성 — baseline 테이블 10만 / 100만 행, mutation 워크로드 테이블의 10%, flush 크기 100 / 500 / 1,000 / 10,000 buffered unit, read 쿼리 4종(full aggregate, range filter, point lookup, TopN)
  • 100만 행 baseline, 10만 update, flush=1,000:
타깃시간생성 오브젝트 수
Iceberg COW269,344 ms806
DuckLake (SQLite 카탈로그)7,075 ms405
DuckLake (DuckDB 카탈로그)6,576 ms405

→ 약 40배 차이. “커피 가져오러 갈 시간” vs “몇 번 눈 깜빡일 시간”

  • 벤치마크의 한계를 명시: PostgreSQL logical replication과 psql-wire 오버헤드를 우회하고 writer/카탈로그 커밋 경로와 로컬 MinIO 위 DuckDB read를 측정한다. 따라서 end-to-end Streambed 벤치마크가 아니라 레이크하우스 타깃 벤치마크로 취급해야 한다
  • 질문은 “DuckLake가 모든 셋업에서 빠른가?”가 아니라 “DuckLake가 작고 반복적인 CDC 스타일 flush를 Iceberg COW 경로보다 잘 다루는가?” 였고 초기 답은 yes

관련 위키


Source: 원문 보기