本文へスキップ
hdknr blog
戻る

Apache Iceberg 入門:データレイクを「テーブル」にする仕組みと DuckDB との関係

S3 に Parquet ファイルを置いておけば、とりあえず Athena や Spark から SQL を投げられます。ただし 1 行だけ直したい、昨日の状態に戻したい、列を 1 つ足したい、となると途端に面倒になります。こうした課題の解決策として広まっているのが Apache Iceberg です。

この記事では、次の 3 つの資料を手がかりに Iceberg の位置づけと仕組みを整理します。後半では、手元の分析でよく使われる DuckDB から Iceberg テーブルを読み書きする方法と、現時点の制約を具体的に見ていきます。

Apache Iceberg とは

Apache Iceberg は、オブジェクトストレージ上に置かれたファイル群を、データベースのテーブルのように扱えるようにするオープンテーブルフォーマットです。Netflix で開発され、のちに Apache Software Foundation に寄贈されました。ライセンスは Apache 2.0 です。

ここで混同しやすいのが Parquet や ORC との関係です。Parquet は「1 つのファイルの中身をどう並べるか」を決めるファイルフォーマットです。一方の Iceberg は、「どのファイルの集まりが、いまこのテーブルを構成しているのか」を管理するテーブルフォーマットです。Iceberg のデータ本体は多くの場合 Parquet で保存されるので、両者は競合せず、レイヤーが違います。

Qiita の記事は、データ基盤を次の 3 層で捉えています。

層役割例
分散ストレージ大量のデータを安く保持するS3、HDFS
計算エンジンクエリを実行するSpark、Trino、Athena、Snowflake、DuckDB
テーブル化技術ファイル群をテーブルとして見せるIceberg、Delta Lake、Hudi

Iceberg はこの 3 層目にあたります。

なぜ今 Iceberg なのか:エンジンとデータの疎結合

Qiita の記事が強調しているのは、技術的な機能よりも設計思想の部分です。

従来の DWH(データウェアハウス)では、ストレージ・テーブル管理・計算エンジンが 1 つの製品に閉じていました。チームごとに別の DWH を使えば、同じデータのコピーがそれぞれに作られ、どれが正しいのか分からなくなります。

Iceberg はテーブル管理の層を OSS の仕様として切り出します。データは S3 に 1 か所だけ置き、BI チームは Snowflake から、データエンジニアは Spark から、アナリストは手元の DuckDB から、という具合に用途ごとにエンジンを選べるようになります。記事はこれを、指標定義の独立になぞらえています。BI ツールの中に埋め込まれていた指標定義を、dbt semantic layer や Cube といった独立したツールで管理するようになった流れです。

その代わり、Qiita の記事も指摘しているとおり、自由度が上がるほど運用とガバナンスは複雑になります。誰がどのエンジンから書き込めるのかを決める仕組みが別途必要です。

従来の S3 データレイクの何がつらいのか

NTTインテグレーションの記事は、S3 中心のデータレイクで起きがちな課題を次のように整理しています。

項目従来の S3 データレイクIceberg
更新・削除1 行の修正でもファイル(パーティション)単位の作り直しになりがちレコード単位の UPDATE / DELETE / MERGE を扱える
履歴管理スナップショットを自前で管理しないと過去の状態に戻せないタイムトラベルで過去の状態を参照できる
スキーマ変更互換性の確認に手間がかかるスキーマ進化を前提にした設計

スキーマ進化とは、列の追加・削除・名前変更などを、既存のデータファイルを書き換えずに行えることです。記事はメリットとして、Hive 方式の運用で負担になりがちなパーティションの追加・修復を意識しなくてよい場面が増える点も挙げています。

これに加えて、AWS の解説ページは ACID トランザクションとインクリメンタル処理(前回から変わった分だけを処理する)を主な特徴に挙げています。

Iceberg の仕組み:カタログ・メタデータ・データの階層

これらの機能は、Iceberg がファイルの上に重ねるメタデータの階層によって実現されています。

Apache Iceberg の構造を示した図。上段に DuckDB・Amazon Athena・Spark/Trino/Flink・Snowflake/Redshift といった計算エンジンが並び、いずれもカタログを経由する。カタログはテーブル名から最新のメタデータファイルの位置を引く役割を持ち、Glue Data Catalog、S3 Tables、REST カタログが該当する。メタデータ層ではメタデータファイルがマニフェストリストを指し、マニフェストリストが複数のマニフェストを指す。マニフェストは S3 上の Parquet データファイルと削除ファイルを指している

カタログ

テーブル名と、そのテーブルの「最新のメタデータファイルがどこにあるか」を対応づける入り口です。AWS なら AWS Glue Data Catalog や Amazon S3 Tables がこの役割を担います。ベンダー中立な Iceberg REST カタログという API 仕様もあり、エンジン側はこれに対応していれば、カタログの実装を問わずに接続できます。

メタデータ層

データ層

実データの Parquet ファイルと、行の削除を記録する削除ファイルです。行を削除するとき、Parquet ファイルを書き直す代わりに「どのファイルの何行目を消したか」を削除ファイルに記録しておき、読み取り時に除外する方式があります。後述する DuckDB の書き込みは、この方式を使います。

構造が機能をどう支えているか

書き込みのたびに新しいファイルが追加され、新しいスナップショットができます。最後にカタログが指すメタデータファイルを新しいものへアトミックに差し替えることで、書き込みは「全部反映されるか、何も反映されないか」のどちらかになります。これが ACID を支えています。

古いスナップショットのメタデータは残っているので、それをたどれば過去の状態を読めます。これがタイムトラベルです。また、マニフェストに列統計があるため、エンジンはファイルを開かずに「この範囲のデータは含まれない」と判断して読み飛ばせます。

パーティションも同じ考え方です。Iceberg では day(event_time) のように「列からパーティション値を導く変換」をテーブル定義に持たせます。クエリは event_time で絞り込むだけで済み、利用者がパーティション用の列を意識する必要がありません。これを hidden partitioning(隠れパーティショニング)と呼びます。

AWS での使い方

NTTインテグレーションの記事は、AWS で Iceberg を使う典型構成を次のように示しています。

  1. 各種ソースから S3 にデータを取り込む
  2. AWS Glue や Amazon EMR で整形し、Iceberg テーブルとして書き込む
  3. 更新・削除・履歴管理は Iceberg に任せる
  4. Amazon Athena などで参照・検証する

AWS の解説ページによると、Athena、EMR、Glue、Redshift、Amazon Data Firehose がそれぞれ Iceberg に対応しています。NTTインテグレーションの記事は、今後の検証対象として Amazon S3 Tables も挙げています。S3 Tables は Iceberg テーブルの保存に特化した S3 のバケット種別で、後述のとおり DuckDB からも直接接続できます。

DuckDB との関係

ここからが本題です。DuckDB はプロセス内で動く分析用データベースで、ノート PC や Lambda のような小さな環境でも動かせます。DuckDB 自体の位置づけは DuckDB・Apache Arrow・Parquetの関係を整理する を参照してください。

冒頭のデータ基盤の 3 層モデルに当てはめると、DuckDB は計算エンジンの 1 つです。Spark クラスタを立てるほどではない規模の分析を、S3 上の Iceberg テーブルに対して直接実行できます。DuckDB からは iceberg 拡張を使ってアクセスします。通常は初回の利用時に自動でインストール・ロードされます。明示する場合は次のとおりです。

INSTALL iceberg;
LOAD iceberg;

テーブルを直接読む(カタログなし)

iceberg_scan にテーブルのディレクトリやメタデータファイルを渡すと、カタログを介さずに読めます。S3 上のテーブルを読む場合は httpfs 拡張と S3 の認証情報も必要です(認証情報は後述の CREATE SECRET で設定します)。

SELECT count(*)
FROM iceberg_scan('s3://bucketname/lineitem_iceberg/metadata/v1.metadata.json');

スナップショットの一覧やタイムトラベルにも対応しています。

-- スナップショットの一覧
SELECT * FROM iceberg_snapshots('data/iceberg/lineitem_iceberg');

-- 特定時点の状態を読む
SELECT count(*)
FROM iceberg_scan(
    'data/iceberg/lineitem_iceberg',
    snapshot_from_timestamp = TIMESTAMP '2023-02-15 15:08:00'
);

ただし、この方法は読み取り専用です。また、どのメタデータファイルが最新かを DuckDB 側では判断できません。そのため、バージョンを明示するか、最新のメタデータのバージョンを書いた version-hint.text ファイルが必要です。上のディレクトリを渡す例も、このファイルがある場合にだけ動きます。最新版を推測させる unsafe_enable_version_guessing という設定もあります。ただし名前のとおり ACID の保証を破る可能性があるため、既定では無効です。

カタログに ATTACH する

本格的に使うなら、カタログに ATTACH します。以下の <...> の部分は、自分の環境の値に置き換えてください。Amazon S3 Tables の場合は次のとおりです。

CREATE SECRET (
    TYPE s3,
    PROVIDER credential_chain
);

ATTACH '<S3 テーブルバケットの ARN>' AS my_catalog (
    TYPE ICEBERG,
    ENDPOINT_TYPE s3_tables
);

AWS Glue Data Catalog の Iceberg REST エンドポイントにつなぐ場合は、SigV4 認証を指定します。

ATTACH '<ACCOUNT_ID>' AS glue_catalog (
    TYPE ICEBERG,
    ENDPOINT 'glue.<REGION>.amazonaws.com/iceberg',
    AUTHORIZATION_TYPE 'sigv4'
);

ATTACH したテーブルには、DuckDB のテーブルと同じように SQL を書けます。カタログ経由なら、書き込みも可能です。次の例は、先ほど my_catalog として ATTACH したカタログに default.events テーブルがある想定です。

SELECT count(*) FROM my_catalog.default.events;

UPDATE my_catalog.default.events SET event_name = 'view' WHERE id = 1;

-- タイムトラベル
SELECT * FROM my_catalog.default.events
AT (TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217');

DuckDB の公式ブログによると、読み取りの全面対応と書き込みの初期対応は v1.4.0 で入り、Iceberg v2 テーブルへの UPDATE / DELETE は v1.4.2 で追加されました。現行のドキュメントには MERGE INTO の例も載っています。

書き込み時の制約

一方で、制約もあります。公式ドキュメントに記載されている主なものは次のとおりです。

現時点では、重い ETL は Glue や EMR の Spark で書き込み、DuckDB は手元での探索や軽い集計、小規模な修正に使う、という分担が無難です。

DuckLake という別の選択肢

DuckDB チームは、Iceberg とは別に DuckLake というテーブルフォーマットも作っています。データを Parquet で持つ点は Iceberg と同じです。違いはメタデータの置き場所です。Iceberg はメタデータを S3 上のファイルとカタログに分けて持ちます。一方 DuckLake は、PostgreSQL などのSQL データベースにメタデータを丸ごと格納します。DuckLake v1.0 は 2026 年 4 月 13 日にリリースされました。

使い分けの目安は単純です。

Iceberg の価値が「エンジンを選べること」にある以上、DuckDB 中心の小さな構成なら DuckLake、組織横断のデータ基盤なら Iceberg、という切り分けになります。

まとめ



前の記事
要求仕様ループを Claude Code プラグインにする — dev-loop と分けて 1 プラグイン・複数スキルで組む
次の記事
Redshift か、S3 + Iceberg のレイクハウスか:DWH とオープンテーブルフォーマットの選び方