아이스버그 테이블 구축은(는) 무엇을 하나요?
사용 시기
- 레이크하우스에서 Apache Iceberg 테이블을 생성하거나 유지 관리할 때.
- 다시 쓰지 않고 파티셔닝을 선택하거나 파티션/스키마를 진화시킬 때.
- 스냅샷, 타임 트래블, 압축, 소규모 파일을 관리할 때.
- 델타 레이크 전용 작업에는 사용하지 마십시오(
engineering-databricks-pipelines사용).
워크플로우
- [ ] 쿼리 필터 열로 파티셔닝, 숨겨진 파티션 변환 사용
- [ ] 멱등적 업서트를 위해 MERGE 사용
- [ ] 소규모 파일 수정을 위해 압축(rewrite_data_files) 예약
- [ ] 오래된 스냅샷 만료 + 고아 파일 제거로 메타데이터/스토리지 제어
- [ ] 필드 ID별로 파티셔닝/스키마 진화(데이터 다시 쓰기 없음)
- 필터 열을 기준으로 파티셔닝하고 숨겨진 파티션 변환(
days(ts),bucket(N, id))을 사용하면, 사용자가 파생된 파티션 열을 추가하지 않아도 쿼리가 프루닝을 수행합니다. - 멱등적 쓰기는 비즈니스 키를 기준으로
MERGE INTO를 통해 수행합니다. - 정기적으로 압축 — 스트리밍/소규모 배치 쓰기는 많은 소규모 파일을 생성합니다.
rewrite_data_files는 읽기 성능을 복원합니다. - 메타데이터 유지 관리 — 오래된 스냅샷을 만료하고 고아 파일을 제거하지 않으면 스냅샷 기록과 스토리지가 무제한으로 증가합니다.
- 자유롭게 진화 — Iceberg는 ID로 열/파티션을 추적하므로, 열 추가/제거/이름 변경 및 파티션 스펙 변경도 데이터 다시 쓰기가 필요 없습니다.
패턴
숨겨진 파티셔닝 + MERGE 업서트로 생성:
CREATE TABLE lake.db.orders (order_id BIGINT, customer_id BIGINT, amount DECIMAL, ordered_at TIMESTAMP)
USING iceberg PARTITIONED BY (days(ordered_at));
MERGE INTO lake.db.orders t USING staging s ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;
유지 관리 (Spark 프로시저):
CALL lake.system.rewrite_data_files('db.orders'); -- 소규모 파일 압축
CALL lake.system.expire_snapshots('db.orders', TIMESTAMP '2026-08-01 00:00:00');
CALL lake.system.remove_orphan_files(table => 'db.orders');
타임 트래블 — 감사 또는 복구를 위해 이전 스냅샷 읽기:
SELECT * FROM lake.db.orders VERSION AS OF <snapshot_id>.
파티션 진화 — ALTER TABLE ... ADD PARTITION FIELD bucket(16, customer_id)는 새 데이터에만 적용되며, 이전 데이터는 그대로 유효합니다.
일반적인 함정
- 스트리밍 테이블에서 압축 미수행 — 소규모 파일 폭증으로 읽기 속도가 저하됩니다.
- 스냅샷을 만료하지 않음 — 메타데이터와 스토리지가 무한정 증가합니다. 타임 트래블 보존 기간 내에 만료를 예약하세요.
- 과도한 파티셔닝(예: 적은 데이터량을 시간 단위로 파티셔닝) — 너무 많은 작은 파티션이 생성됩니다. 데이터 크기에 맞게 세분화를 조정하세요.
- 명시적 파생 파티션 열 추가 — 숨겨진 파티셔닝의 목적을 무효화합니다. 변환을 사용하세요.
- MERGE 대신 블라인드 덮어쓰기 — 멱등성을 잃습니다. 키로 MERGE하세요.
- 너무 짧은 기간으로 고아 파일 제거 — 진행 중인 작성자가 여전히 필요한 파일을 삭제할 수 있습니다. 안전한 기준 시간을 사용하세요.