Iceberg 테이블은 쓰기가 일어날 때마다 스냅샷을 새로 만든다. 지우지 않으면 스냅샷이 참조하는 데이터 파일이 계속 남아 스토리지가 실제 데이터의 몇 배로 불어나고, manifest 수가 늘어 조회 계획 수립도 느려진다. 정리는 자동으로 되지 않는다 — 저장소 관리자가 주기적으로 돌려야 한다.
Iceberg 는 테이블에 딸린 메타데이터 테이블로 현재 상태를 SQL 로 보여준다. Spark · Trino · Flink 에서 쓸 수 있다.
SELECT * FROM my_db.my_table.snapshots; -- 스냅샷 목록, 작업 종류, 시각
SELECT * FROM my_db.my_table.history; -- 스냅샷 계보
SELECT * FROM my_db.my_table.files; -- 현재 스냅샷의 데이터 파일 경로와 크기
SELECT * FROM my_db.my_table.manifests; -- manifest 목록
SELECT * FROM my_db.my_table.refs; -- 브랜치와 태그
Impala 에서는 메타데이터 테이블 조회가 제한적이다. 최소한 테이블이 Iceberg 인지와 저장 위치는 확인할 수 있다.
DESCRIBE FORMATTED my_db.my_table;
스토리지에서 직접 보면 구조가 그대로 보인다. metadata/ 아래에 *.metadata.json · snap-*.avro(manifest list) · *.avro(manifest) 가, data/ 아래에 실제 데이터 파일이 있다.
hdfs dfs -ls -R /warehouse/my_db.db/my_table/
오래된 스냅샷을 없애면 그 스냅샷만 참조하던 데이터 파일과 manifest 가 같이 지워진다. Spark 의 저장 프로시저를 쓴다.
CALL my_catalog.system.expire_snapshots(
table => 'my_db.my_table',
older_than => TIMESTAMP '2026-09-01 00:00:00',
retain_last => 5
);
retain_last 는 시간 조건과 무관하게 최근 N개를 남긴다. 둘을 같이 주는 편이 안전하다 — 시간 조건만 주면 오래 갱신되지 않은 테이블에서 스냅샷이 하나도 남지 않을 수 있다.
만료한 스냅샷으로는 타임 트래블도 롤백도 못 한다. 감사나 되돌리기 목적으로 보관 기간이 정해져 있다면 그 기간보다 짧게 잡지 않는다.
테이블 속성으로 기준을 박아 두면 이후 호출에서 인자를 생략해도 된다.
ALTER TABLE my_db.my_table SET TBLPROPERTIES (
'history.expire.min-snapshots-to-keep'='5',
'history.expire.max-snapshot-age-ms'='604800000'
);
이 속성만 넣어 두면 알아서 지워지는 것은 아니다. 만료 작업 자체는 여전히 호출해야 한다.
커밋이 실패했거나 작업이 중간에 죽으면 메타데이터가 가리키지 않는 파일이 남는다.
CALL my_catalog.system.remove_orphan_files(
table => 'my_db.my_table',
older_than => TIMESTAMP '2026-09-13 00:00:00'
);
older_than 을 반드시 준다. 기본값은 사흘 전이고, 이보다 짧게 잡으면 지금 쓰고 있는 중인 파일을 지울 수 있다. 다른 작업이 같은 테이블에 쓰는 동안에는 돌리지 않는다.
테이블 디렉터리에 Iceberg 가 모르는 파일(로그, 임시 산출물)을 같이 두었다면 이 명령이 그것도 지운다. 돌리기 전에 목록을 먼저 확인한다.
작은 manifest 가 많아지면 조회 계획을 세울 때 읽어야 할 파일이 늘어난다.
CALL my_catalog.system.rewrite_manifests(table => 'my_db.my_table');
데이터 파일 자체를 합치는 것은 별개의 작업이다. merge-on-read 로 쌓인 delete 파일도 여기서 걷힌다.
CALL my_catalog.system.rewrite_data_files(table => 'my_db.my_table');
DROP TABLE 은 카탈로그에서 테이블을 떼어 낼 뿐, 데이터 파일은 보통 그대로 남는다.
DROP TABLE my_db.my_table PURGE;
PURGE 를 붙이면 데이터까지 지운다. 다만 카탈로그 구현마다 동작이 다르다 — Hive Metastore 기반 카탈로그에서는 외부 테이블로 잡혀 있으면 파일이 남는 경우가 있다. 지웠다고 생각하고 넘어가지 말고 스토리지에서 한 번 확인한다.
hdfs dfs -du -s -h /warehouse/my_db.db/my_table/
남아 있으면 경로를 직접 지운다.
세 작업의 성격이 다르다.
| 작업 | 목적 | 권장 주기 |
|---|---|---|
expire_snapshots |
오래된 스냅샷과 그 데이터 파일 제거 | 보관 정책에 맞춰 매일 또는 매주 |
rewrite_data_files |
작은 파일과 delete 파일 병합 | 수집량에 따라 매일 또는 매주 |
rewrite_manifests |
manifest 조각 병합 | 월 단위로 충분한 경우가 많다 |
remove_orphan_files |
커밋 실패 잔재 제거 | 월 단위. 다른 쓰기 작업이 없는 시간에 |
rewrite_data_files 를 먼저 돌리고 expire_snapshots 를 돌린다. 순서를 뒤집으면 방금 병합해서 버려진 옛 파일이 스냅샷에 묶여 다음 주기까지 남는다.