Puffin-Backed Derived Data

열린 테이블 포맷은 파생 데이터 생명주기를 공짜로 제공한다


핵심 개념

Iceberg의 Puffin은 원래 테이블 통계(distinct-value 추정용 Theta sketch, 파티션 프루닝용 bloom filter)와 deletion vector를 담으려고 도입된 플랫 바이너리 컨테이너다. 그런데 스펙이 의도적으로 확장 가능하게 설계되어 있다.

각 blob은 다음을 갖는다.

  • 불투명한 type 문자열
  • Iceberg field-ID 집합
  • 임의의 property map
  • 바이트 페이로드

그리고 Puffin 파일 하나는 스냅샷의 statistics-file summary property 하나로 바인딩된다.

이 조합이 만드는 결과가 핵심이다: 스냅샷을 읽는 엔진은 footer를 검사해 자기가 아는 타입의 blob만 선택적으로 읽고, 모르는 타입은 에러 없이 무시한다. blob마다 독립 압축되고 byte-range 요청으로 개별 주소 지정이 가능해서, 전체 다운로드가 비현실적인 대용량에도 쓸 수 있다.

왜 이 슬롯이 중요한가

compute-disaggregated 엔진(Snowflake가 대중화하고 lakehouse가 일반화한 설계)에서 파생 상태를 두는 것은 까다롭다. 유지해야 할 네 가지 속성이 있다.

속성의미
stateless executor언제든 종료·교체 가능해야 한다. 로컬 디스크 전용 상태는 탄력적 스케일링과 양립 불가
single source of truth파생 상태(인덱스, 통계)가 계산 기준이 된 데이터 버전과 일관되어야 한다
멀티엔진 상호운용여러 엔진이 같은 데이터를 읽는데, 파생 산출물이 이를 깨뜨리면 안 된다
새 생명주기 없음생성·리프레시·삭제가 테이블 포맷의 트랜잭션 커밋·시간여행·GC를 재사용해야 한다

파생 구조는 (a) 기저 데이터에서 재계산 가능하거나 (b) 테이블 포맷 자체에 커밋되어야 한다. Puffin은 (b)의 표준화된 자리다.

대표 사례 — ANN 벡터 인덱스

십억 규모 벡터 검색을 lakehouse 엔진에 붙이는 관습적 방법들 — 별도 벡터 DB, executor의 사설 인덱스 파일시스템, 쿼리마다 재구축 — 은 위 네 속성 중 최소 하나를 위반한다.

Puffin에 DiskANN/Vamana 그래프를 넣으면 다음이 구현 비용 없이 따라온다.

  • 원자성 — 인덱스 커밋이 Iceberg 스냅샷 커밋
  • 시간여행 — 인덱스 버전 = 스냅샷 버전. AS OF 쿼리가 자동으로 맞는 인덱스 버전을 읽는다
  • 동시성 중재 — 동시 인덱스 빌드를 동시 데이터 쓰기와 같은 optimistic concurrency가 처리
  • orphan GC — 옛 Puffin 파일은 참조가 사라지면 테이블 포맷의 기존 orphan-file 정리가 회수
  • incremental refresh — manifest diff가 두 스냅샷 사이의 추가·제거·불변 데이터 파일을 정확히 반환하므로 영향받은 샤드만 리프레시

구조적 재사용

인덱스 빌드는 Parquet 대신 Puffin 파일을 만드는 INSERT-SELECT다. 기존 fragment dispatch·S3 I/O·cache-aware 스케줄링·REST 커밋을 그대로 쓴다. 리프레시된 Puffin의 커밋은 metadata-only — 데이터 파일은 그대로이고 summary가 새 경로를 가리킬 뿐이다.

실제 구현(Teradata의 FlockDB, DuckDB 기반 MPP)에서 신규 코드 약 8,000줄 중 대부분이 그래프 빌더였고 PuffinWriter는 약 200줄, 테이블 포맷 통합은 수백 줄이었다. 통합 비용이 알고리즘 비용의 잡음 수준이라는 것이 이 패턴의 논증이다.

얻는 것 (10억 벡터, 768차원, executor 4대)

인덱스 없음Centroid (coord.)DiskANN (분산)
스캔 파일10,000~400~50
S3 읽기300 GB12 GB1.5 GB
warm 레이턴시15–25s2–4s50–200ms
Recall@1001.000.85–0.950.95–0.99

치러야 할 대가

  • 업데이트 granularity가 스냅샷 — 벡터가 Iceberg 커밋과 독립적으로 검색 가능해질 수 없다. 스트리밍 신선도 요구에서는 커밋 주기가 인덱스 신선도의 상한이고, 분당 수천 커밋은 REST 카탈로그를 포화시킨다
  • stage barrier가 레이턴시 하한을 정한다 — 분산 probe의 barrier 2개가 각 5~10ms. sub-10ms P50 애플리케이션에는 과하고 단일 단계 로컬 인덱스가 맞다
  • 독립 샤드 설계의 recall 손실 — oversampling과 exact rerank로 대부분 회복되지만 형식적 하한 보장은 없다
  • 인덱스가 데이터만큼 크거나 더 클 수 있다 — 그래프 기반 ANN의 표준적 트레이드오프

패턴은 ANN 전용이 아니다

테이블 데이터에서 파생되고, 스냅샷과 함께 버전되며, 일부 엔진만 읽으면 되는 것은 무엇이든 Puffin 후보다.

  • 학습된 인덱스·cardinality 모델 — 컬럼별로 학습된 분포 모델을 blob으로 저장하고 그것을 쓸 줄 아는 옵티마이저가 소비
  • materialized derived column — 계산된 집계, 파생 임베딩, 비정규화 조인 컬럼을 blob에 두고 가상 컬럼으로 질의. 스냅샷 바인딩이 기저 데이터와의 일관성을 보장한다
  • 엔진 간 가속 공유 — 한 엔진이 만든 인덱스를 다른 엔진이 소비. blob 포맷 합의가 전제 조건이라 커뮤니티 표준 논의가 필요하다 (ann-routing-v1, ann-vamana-graph-v1, ann-centroid-index-v1이 제안된 후보)

패턴은 Delta Lake의 deletion vector·statistics file과 Hudi의 metadata table에도 깔끔히 전이된다. 같은 아키텍처 슬롯을 차지하기 때문이다.

넓게 보면 Puffin이 테이블 통계용을 넘어 스냅샷 시맨틱에 묶인 범용 append-only key-value 스토어로 쓰이기 시작하는 중이다.

연관 개념


Source: Puffin-Backed Vector Indexes