【AWS】Iceberg テーブルの運用コスト最適化 — コンパクション・メンテナンス・ストレージ戦略
はじめに
前回の「Apache Iceberg 実践入門」では、Iceberg の基本概念から Athena での実践的な操作、メダリオンアーキテクチャまでを解説しました。
Iceberg を導入すると、ACID トランザクション、タイムトラベル、スキーマエボリューションといった強力な機能が手に入ります。しかし運用フェーズに入ると、クエリコスト以外の運用コストが無視できなくなります。
- コンパクションの実行コストが月額で想定以上に膨らむ
- スナップショットの蓄積でストレージ料金が倍増する
- S3 API コールの課金が予想外に高い
- S3 Tables と汎用 S3 のどちらが本当に安いのか判断できない
この記事では、Iceberg テーブルの運用コストにフォーカスし、方式別のコスト比較と選定ガイドを提供します。具体的な金額と SQL サンプルを交えて、コスト最適化のための実践的な判断基準を整理します。
この記事で得られること:
- コンパクション 4 方式(Athena / Glue / EMR / S3 Tables)のコスト比較
- Athena VACUUM を活用したスナップショット管理の自動化
- S3 Tables vs 汎用 S3 の TCO(総所有コスト)比較
- CoW / MoR の書き込みコスト影響
- Iceberg 前提での Athena vs Redshift Serverless エンジン選定
前提: 料金は US East (N. Virginia) リージョン、2026 年 2 月時点の公開価格です。東京リージョンではストレージ料金が約 9% 高くなります。
Iceberg 運用で発生する 4 つのコスト要因
Iceberg テーブルの運用コストは、クエリ料金(Athena の $5/TB スキャン課金など)だけではありません。以下の 4 つの要因が複合的にコストを押し上げます。
| コスト要因 | 発生原因 | 放置した場合の影響 |
|---|---|---|
| コンパクション | ストリーミングや頻繁な INSERT でスモールファイルが蓄積 | クエリ性能悪化 + コンパクション実行コスト |
| スナップショット蓄積 | 全トランザクションで新スナップショットが生成 | ストレージ料金の肥大化 |
| S3 API コール | メタデータ読み取り(Manifest List / Manifest File)が S3 GET で課金 | ファイル数に比例して API 料金が増加 |
| Write Amplification | CoW での UPDATE/DELETE がファイル全体を再作成 | 書き込みコストとストレージの一時的倍増 |
これらは相互に関連しています。たとえばコンパクションを怠るとスモールファイルが増え、S3 API コールも増加します。逆にコンパクションを適切に実行すれば、ファイル数が減って API コストも下がるという好循環が生まれます。
以下、各コスト要因について方式別の比較と最適化戦略を解説します。
コンパクション — 方式別コスト比較と選定ガイド
コンパクション(スモールファイル問題の解消)は Iceberg テーブルの必須の運用タスクです。前回も触れましたが、ここでは実行方式によるコストの違いに焦点を当てます。
4 方式のコスト比較
| 方式 | 課金モデル | 単価(US East) | 100 GB 処理時 | 運用負荷 |
|---|---|---|---|---|
| Athena OPTIMIZE | スキャンデータ量 | $5.00/TB | $0.50 | 最小(SQL 1 文) |
| Glue 自動コンパクション | DPU(Data Processing Unit)時間 | $0.44/DPU-hour | $0.44 | 低(設定のみ) |
| EMR Spark | インスタンス時間 | 可変 | $0.17 | 高(クラスタ管理) |
| S3 Tables 自動 | オブジェクト数 + データ量 | $0.002/1K obj + $0.005/GB | $0.52 | なし(全自動) |
注: Glue 自動コンパクションは 2 DPU x 30 分で試算。EMR は m5.xlarge スポットインスタンスで試算。S3 Tables は 2025 年 7 月の価格改定後の価格(Binpack のバイト単価が 90% 低下、オブジェクト単価が 50% 低下。独立検証で指摘された 20-30 倍のコスト差に対する AWS の迅速な対応)。
方式別の特徴
Athena OPTIMIZE — 小規模テーブルの手軽な選択肢
-- テーブル全体のコンパクション
OPTIMIZE my_db.my_table REWRITE DATA USING BIN_PACK;
-- 特定パーティションに絞る(identity パーティションカラムのみ指定可)
OPTIMIZE my_db.my_table REWRITE DATA USING BIN_PACK
WHERE region = 'ap-northeast-1';
- メリット: 追加のインフラ不要。SQL 1 文で即座に実行可能
- デメリット: $5/TB のスキャン課金。大規模テーブルでは割高
- 適するケース: 数百 GB 以下のテーブル、手動または低頻度の実行
制約:
OPTIMIZEの WHERE 句には identity パーティションカラムのみ指定可能です。month(sale_date)のような隠しパーティション変換は使用できません。
Glue 自動コンパクション — 中規模テーブルのバランス型
Glue テーブルオプティマイザの機能として提供されます。
- メリット: スケジュール不要(Glue が自動判断で実行)。Binpack / Sort / Z-order 対応
- デメリット: $0.44/DPU-hour の DPU 課金(1 秒単位で課金、最低 1 分/実行)
- 適するケース: 数百 GB〜数 TB のテーブル、定期的なコンパクションが必要な環境
Glue コンソールまたは API でテーブルごとに最適化設定を有効化します。一度設定すれば、Glue がファイルサイズやファイル数を監視し、必要に応じて自動でコンパクションを実行します。
EMR Spark — 大規模テーブルの最安選択肢
# EMR Spark でのコンパクション実行例
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.config("spark.sql.catalog.glue_catalog", "org.apache.iceberg.spark.SparkCatalog") \
.config("spark.sql.catalog.glue_catalog.catalog-impl", "org.apache.iceberg.aws.glue.GlueCatalog") \
.config("spark.sql.catalog.glue_catalog.warehouse", "s3://my-data-lake/warehouse") \
.getOrCreate()
# Binpack コンパクション
spark.sql("""
CALL glue_catalog.system.rewrite_data_files(
table => 'my_db.my_table',
strategy => 'binpack',
options => map('target-file-size-bytes', '134217728')
)
""")
- メリット: インスタンス料金のみ。スポットインスタンスで最大 90% 削減可能
- デメリット: クラスタ管理・ジョブスケジューリングの運用負荷
- 適するケース: 数 TB 以上のテーブル、既存の EMR 基盤がある環境
ベストプラクティス: コンパクション専用クラスタをクエリ処理クラスタとは分離し、リソース競合を回避します。
S3 Tables 自動コンパクション — 運用ゼロの選択肢
S3 Tables ではコンパクションが自動実行されます。追加設定は不要です。
- メリット: 完全自動。運用負荷ゼロ
- デメリット: 2025 年 7 月の価格改定で大幅に値下げされたが、EMR 自己管理と比較すると依然約 3 倍のコスト差(OneHouse の独立検証による)
- 適するケース: 運用チームが小さく、メンテナンスの自動化が最優先
選定の目安
| テーブル規模・更新頻度 | 推奨方式 |
|---|---|
| 〜数百 GB / 低頻度 | Athena OPTIMIZE(最も手軽) |
| 数百 GB〜数 TB / 定期 | Glue 自動コンパクション(バランス型) |
| 数 TB〜 / 高頻度 | EMR Spark(最安・既存基盤向け) |
| 運用負荷最小化が最優先 | S3 Tables(全自動) |
スナップショット・メタデータ管理 — 放置コストとクリーンアップ戦略
なぜスナップショットを放置するとコストが膨らむのか
Iceberg はすべてのトランザクションで新しいスナップショットを生成します。INSERT、UPDATE、DELETE、MERGE INTO、そして OPTIMIZE によるコンパクションも例外ではありません。
放置した場合に膨らむコスト要因:
| コスト要因 | 詳細 |
|---|---|
| S3 ストレージ | 期限切れスナップショットが参照する旧データファイルが削除されずに蓄積 |
| S3 API コール | クエリプランニング時の Manifest List / Manifest File 読み取り回数が増加 |
| メタデータファイル |
metadata.json のスナップショット一覧が肥大化し、クエリ起動のオーバーヘッドが増大 |
| 孤立ファイル | 失敗したトランザクションが残したデータファイルがストレージを消費 |
クリーンアップ方式の比較
| 方式 | コンピュートコスト | 対象 | 特徴 |
|---|---|---|---|
| Athena VACUUM | 無料 | スナップショット + 孤立ファイル | 最もコスト効率が高い |
| Glue スナップショット保持 | DPU 時間課金 | スナップショット + 関連ファイル | 保持期間を設定するだけ |
| EMR expire_snapshots | インスタンス時間 | スナップショット | 細かい制御が可能 |
| S3 Tables 自動管理 | 料金に含む | 全対象 | 完全自動 |
Athena VACUUM — コンピュート無料の最適解
Athena VACUUM はコンピュート料金が無料で、発生するのは S3 API コール(DELETE リクエスト)の料金のみです。これはスナップショット管理において圧倒的なコスト優位性を持ちます。
-- デフォルト設定で VACUUM を実行
-- 5 日以上前のスナップショットと孤立ファイルを削除
VACUUM my_db.my_table;
VACUUM は以下の 2 つの処理を実行します:
-
スナップショット期限切れ:
vacuum_max_snapshot_age_secondsより古いスナップショットを削除 - 孤立ファイル削除: テーブル状態に含まれないファイルを検出・削除
-- 保持期間のカスタマイズ
ALTER TABLE my_db.my_table SET TBLPROPERTIES (
'vacuum_max_snapshot_age_seconds' = '259200' -- 3日に短縮
);
-- 孤立ファイルの保持期間も調整可能
ALTER TABLE my_db.my_table SET TBLPROPERTIES (
'vacuum_min_snapshots_to_keep' = '3' -- 最低 3 スナップショットを保持
);
制約:
- 1 回の実行で最大 20,000 オブジェクトを削除。上限に達すると
ICEBERG_VACUUM_MORE_RUNS_NEEDEDエラーが返されるため、自動化パイプラインではリトライロジックを組み込む - 削除したスナップショットへのタイムトラベルは不可能になる
- 監査用に残したいスナップショットは事前にタグ付けしておく
-- 重要なスナップショットをタグで保護(Spark / EMR で実行)
-- ※ Athena では CREATE TAG は未サポート
ALTER TABLE my_db.my_table CREATE TAG `EOM-2026-01` AS OF VERSION 30 RETAIN 365 DAYS;
VACUUM の自動化 — Step Functions + EventBridge
VACUUM は手動で毎回実行するのではなく、自動化するのが実用的です。$0.01 未満/回のコストで定期実行できます。
EventBridge(日次/週次)→ Step Functions → Athena VACUUM の順に実行します。VACUUM が ICEBERG_VACUUM_MORE_RUNS_NEEDED を返した場合はリトライし、完了後に次のテーブルの VACUUM に進みます。
推奨スケジュール:
| テーブルの更新頻度 | VACUUM 実行頻度 | 理由 |
|---|---|---|
| ストリーミング(常時書き込み) | 日次 | スナップショットが高速に蓄積 |
| バッチ(日次 ETL) | 週次 | 日次 ETL の 7 日分を一括クリーンアップ |
| 低頻度(月次ロード) | 月次 | 蓄積速度が遅いため月次で十分 |
メタデータ自動クリーンアップ
VACUUM に加えて、メタデータファイル自体の肥大化も防ぎます。
-- 古いメタデータファイルの自動削除を有効化
ALTER TABLE my_db.my_table SET TBLPROPERTIES (
'write.metadata.delete-after-commit.enabled' = 'true',
'write.metadata.previous-versions-max' = '10'
);
これにより、コミットのたびに古い metadata.json が自動削除され、メタデータディレクトリの肥大化を防止します。
S3 API コスト — コンパクションによる間接的な削減
Iceberg のクエリプランニングでは、Manifest List → Manifest File の順に S3 GET リクエストを発行してデータファイルの一覧を取得します。スモールファイルが多いテーブルではファイル数に比例して Manifest File のエントリ数が増え、S3 GET リクエスト料金が想定外に膨らむことがあります。
| 状況 | Manifest File 内のエントリ数 | クエリあたり S3 GET 概算 |
|---|---|---|
| コンパクション前(10 KB x 100 万ファイル) | 100 万 | 数千リクエスト |
| コンパクション後(128 MB x 80 ファイル) | 80 | 数十リクエスト |
S3 GET は $0.0004/1,000 リクエストと安価ですが、高頻度クエリ環境ではクエリ回数 x ファイル数で急増します。コンパクションによるファイル数削減は、直接的なクエリ性能改善に加えて S3 API コストの間接的な削減にもつながります。
S3 Tables vs 汎用 S3 — TCO で比較する
2024 年 12 月に登場した S3 Tables は、Iceberg に最適化されたストレージを提供します。しかし「S3 Tables = 常に安い」わけではありません。TCO(総所有コスト)で比較します。
料金体系の違い
| 項目 | 汎用 S3 Standard | S3 Tables |
|---|---|---|
| ストレージ | $0.023/GB | $0.0265/GB(+15%) |
| PUT リクエスト | $0.005/1,000 | $0.005/1,000 |
| GET リクエスト | $0.0004/1,000 | $0.0004/1,000 |
| オブジェクトモニタリング | なし | $0.025/1,000 objects |
| コンパクション | 自己管理 | $0.002/1K objects + $0.005/GB |
| スナップショット管理 | 自己管理 | 自動(料金に含む) |
TCO 比較シナリオ
前提: 1 TB の Iceberg テーブル、日次コンパクション、週次スナップショットクリーンアップ
| コスト項目 | 汎用 S3 + Athena | 汎用 S3 + Glue 自動 | S3 Tables |
|---|---|---|---|
| ストレージ(月額) | $23.00 | $23.00 | $26.50 |
| コンパクション(月額) | $1.50 ※1 | $13.20 | 含む |
| スナップショット管理(月額) | $0.04 | $2.00 | 含む |
| モニタリング(月額) | — | — | $2.50 |
| コンパクション処理費(月額) | — | — | ~$5.12 |
| 合計(月額) | $24.54 | $38.20 | ~$34.12 |
※1: Athena OPTIMIZE は $5/TB だが、日次コンパクションでは前回以降の差分ファイルのみが書き換え対象になるため、毎回 1 TB 全体をスキャンするわけではない。300 MB/日の新規データ想定で試算。
「汎用 S3 + Athena」が最安: Athena OPTIMIZE ($5/TB) + VACUUM(無料)の組み合わせは、手動運用を許容すれば最もコスト効率が高い構成です。
S3 Tables の真価 — コスト以外の要素
S3 Tables の強みはコストだけではありません:
- 最大 3 倍のクエリスループット(S3 のストレージ最適化による)
- 最大 10 倍のトランザクション/秒
- 自動メンテナンスによる運用負荷ゼロ
- 2025 年 12 月に Intelligent-Tiering 対応(アクセスパターンに基づき Frequent Access → Infrequent Access → Archive Instant Access の 3 層を自動移行。AWS 公式では最大 80% のコスト削減)
- 2026 年 3 月に IAM ベースの簡易パーミッション対応(ストレージ・カタログ・クエリエンジンの権限を単一の IAM ポリシーで定義可能。Lake Formation なしでも利用開始できる)
S3 Tables の選定基準
| 判断軸 | 汎用 S3 を選ぶ | S3 Tables を選ぶ |
|---|---|---|
| コスト優先 | Athena OPTIMIZE/VACUUM で自己管理 | — |
| 運用負荷 | 専任チームがいる | チームが小さい、運用を自動化したい |
| スループット | 十分なパフォーマンス | 高スループットが必要 |
| 書き込み頻度 | バッチ日次ロード | ストリーミング、高頻度書き込み |
| 既存基盤 | EMR/Glue の運用基盤がある | 新規構築 |
CoW vs MoR — コスト視点での選択
第 1 弾で CoW(Copy-on-Write)と MoR(Merge-on-Read)の基本を紹介しました。ここではコストへの影響を定量的に比較します。
Write Amplification(書き込み増幅)のコスト影響
| 方式 | 1 行更新時の動作 | 書き込みコスト | ストレージへの影響 |
|---|---|---|---|
| CoW | 対象行を含むファイル全体(数百 MB)を再作成 | 高い | 旧ファイル + 新ファイルで一時的に倍増 |
| MoR | Delete File(数 KB)+ 新データのみ書き込み | 低い | Delete File の蓄積は小さい |
ワークロード別のコスト比較
シナリオ: 1 TB テーブル、月間 100 万行の更新(128 MB/ファイル、1,000 ファイル x 1,000 行/ファイル想定。更新対象が全ファイルに分散する最悪ケース)
| 項目 | CoW | MoR |
|---|---|---|
| 1 回の UPDATE による書き込み | 128 MB(ファイル全体再作成) | ~数 KB(Delete File + 新行) |
| 月間書き込み量(100 万行) | ~128 GB(1,000 ファイル書き換え) | ~数 MB(Delete File のみ) |
| S3 PUT コスト(月額) | ~$0.005(1,000 PUT) | ~$0.005(1,000 PUT + 1,000 Delete File) |
| 読み取りコスト(Athena) | 最適(最新データのみスキャン) | やや高い(Delete File マージのオーバーヘッド) |
| コンパクション頻度 | 低い | 高い(Delete File 蓄積の解消が必要) |
| 総コスト(読み取り重視) | 有利 | やや不利 |
| 総コスト(書き込み重視) | 不利 | 有利(書き込み量を大幅に削減) |
ポイント: CoW の真のコストは S3 PUT 料金よりも、ファイル再作成に伴うスキャン課金(MERGE INTO 時に Athena が対象ファイルを読み取る $5/TB)にあります。MoR はこの読み取り+再書き込みを回避するため、更新頻度が高いほどコスト差が拡大します。
CoW / MoR の選定基準
- バッチ更新(日次/週次): CoW を推奨。書き込み頻度が低いため増幅の影響が小さく、読み取りコストが最適
- ストリーミング + 頻繁な更新: MoR を推奨。MERGE INTO のコストを最大 66% 削減可能。ただし定期的なコンパクションが必須
- Athena は常に MoR で動作(CoW は未サポート)。Spark(EMR / Glue ETL)では TBLPROPERTIES で明示的に CoW / MoR を選択可能:
-- CoW / MoR の設定例(Spark / EMR / Glue ETL で実行。Athena では無視される)
ALTER TABLE my_db.my_table SET TBLPROPERTIES (
'write.delete.mode' = 'merge-on-read',
'write.update.mode' = 'merge-on-read',
'write.merge.mode' = 'merge-on-read'
);
注意: MoR ではコンパクションの実行頻度を上げる必要があります。Delete File が蓄積すると読み取りパフォーマンスが低下し、結果的にコスト増につながります。Athena は常に MoR のため、Athena で行レベル操作を行う場合は定期的なコンパクションが必須です。
Athena vs Redshift Serverless — Iceberg 前提のエンジン選定
Schema on Write/Read の解説記事では Athena と Redshift Serverless の一般的なコスト比較を行いましたが、Iceberg テーブルを前提にすると考慮点が変わります。なお、エンジン選定の詳細(マルチエンジン連携のアーキテクチャ)は第 4 弾「Iceberg データレイクハウスの高度な設計」で解説します。
Iceberg 固有の追加コスト要因
| 要因 | Athena | Redshift Serverless |
|---|---|---|
| テーブルメンテナンス | OPTIMIZE($5/TB)+ VACUUM(無料) | RPU 時間に含まれる |
| メタデータ読み取り | S3 API 課金(Manifest の GET) | RPU 時間に含まれる |
| 外部テーブルスキャン | — | Spectrum スキャン料金が RPU に包含 |
Redshift Serverless の隠れたメリット: Iceberg テーブルへのクエリでは、Spectrum のスキャン料金(通常 $5/TB)が RPU 時間に含まれます。大量スキャンが発生する分析ワークロードでは、Athena の従量課金よりも安くなるケースがあります。
ワークロード別選定マトリクス
| シナリオ | 推奨エンジン | 理由 |
|---|---|---|
| アドホック分析(低頻度) | Athena | クエリ時のみ課金。VACUUM 無料でメンテナンスコスト最小 |
| BI ダッシュボード(中頻度) | Redshift Serverless | マテリアライズドビューでスキャン削減。キャッシュ活用 |
| バッチ ETL | Athena + Glue | Athena CTAS で効率的にロード。Glue でコンパクション自動化 |
| ストリーミング + リアルタイム分析 | Redshift Serverless | MoR の読み取りオーバーヘッドが RPU に吸収される |
| コスト最小化が最優先 | Athena | VACUUM 無料 + スキャン量課金で予測しやすい |
| 運用負荷最小化が最優先 | S3 Tables + Athena | 全自動メンテナンス + サーバーレスクエリ |
まとめ — コスト最適化チェックリスト
Iceberg テーブルの運用コストを最適化するためのチェックリストです。
コンパクション:
- テーブル規模に応じた方式を選定(小規模: Athena OPTIMIZE / 中規模: Glue 自動 / 大規模: EMR)
- ストリーミングテーブルは 1〜4 時間ごと、バッチテーブルは日次でコンパクションを実行
- ターゲットファイルサイズは 100 MB〜数百 MB に設定
スナップショット管理:
- Athena VACUUM を定期実行(コンピュート無料)
- Step Functions + EventBridge で自動化
- 監査用スナップショットはタグで保護
-
write.metadata.delete-after-commit.enabled = trueでメタデータ自動クリーンアップ
ストレージ戦略:
- TCO で S3 Tables vs 汎用 S3 を比較(コスト最優先なら汎用 S3 + Athena が最安)
- S3 Intelligent-Tiering を有効化(ただし Archive Access ティアは使用しない。S3 Tables では 2025 年 12 月から自動対応)
書き込み方式:
- バッチ更新中心なら CoW(デフォルト)、ストリーミング + 頻繁な更新なら MoR を検討
- MoR 使用時はコンパクション頻度を上げる
エンジン選定:
- アドホック・低頻度なら Athena、高頻度・大量結合なら Redshift Serverless
- Redshift Serverless の Spectrum スキャン包含を考慮して TCO を比較
Iceberg シリーズ: