0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Apache Icebergの基礎知識と最新動向|データレイクハウスを支える仕組み・アーキテクチャ・処理の流れを解説

0
Last updated at Posted at 2026-09-16

著者: 伊藤 雅博, 株式会社日立製作所

はじめに

本稿では、データレイクハウスを実現するオープンなテーブルフォーマットである Apache Iceberg について、その登場した背景から概要、ユースケース、内部アーキテクチャ、実際の更新・参照処理の流れまでを解説します。

近年、大量データの分析基盤として「データレイクハウス」というアーキテクチャが注目されています。Apache Icebergは、このデータレイクハウスを実現する代表的なテーブルフォーマットであり、主要なOSS、クラウドサービス、商用データ基盤で幅広くサポートされています。

Apache Icebergが登場した背景

データレイクからデータレイクハウスへ

SQLデータベースのワークロードは、OLTP (Online Transaction Processing) と OLAP (Online Analytical Processing) の2つに大別されます。

項目 OLTP OLAP
名称 オンライントランザクション処理 オンライン分析処理
ワークロード 小さいデータを高頻度で更新・参照 大量データを読み出して集計・分析
主なユースケース 口座残高の管理などの基幹系/業務系システム BI(ビジネス・インテリジェンス)などの情報系/分析系システム
データベース種別 RDBMS(PostgreSQL, MySQLなど) データウェアハウス(DWH)

このうちOLAP向けのデータベースは、従来データウェアハウスが主流でした。

データウェアハウスを利用する場合は、生データ(非構造データ)を一旦データレイクに蓄積して、前処理(加工・欠損値補完など)を行い整形してから、データウェアハウスに格納してSQLで分析する モダンデータレイク・アーキテクチャ が一般的です。

しかし、扱うデータの多様化・大規模化に伴い、データレイク上のデータに対して直接SQLを実行する データレイクハウス・アーキテクチャ への移行が進んでいます。これは、高速なSQLとトランザクションをデータレイク上で実現することで、運用・管理コストを削減するアプローチです。

fig01_olap_architecture.png

データレイクハウスは、データレイクとデータウェアハウスの両方の利点を持ちます。

項目 データレイク データウェアハウス(DWH) データレイクハウス
概要 データをファイルのまま蓄積し任意の並列分散処理エンジンで分析 テーブルデータをSQLで高速分析する専用DB データレイク上でDWHに近い性能とトランザクションを実現
対応データ形式 構造化/非構造化データ 構造化データ(表形式) 構造化/非構造化データ
ACIDトランザクション 非対応 対応 対応
参照性能 中 高 高
更新性能 低 中 中
コスト 低コストのストレージ 高コストの専用DB 低コストのストレージ
主要製品 Hadoop (HDFS), Amazon S3, Azure Data Lake Storage, Google Cloud Storage Teradata, Amazon Redshift, Google BigQuery, Snowflake Apache Iceberg, Apache Hudi, Delta Lake

Apache Icebergは、データレイク上にデータレイクハウスを実現するデータ管理層である テーブルフォーマット(Table Format) を提供します。

データレイクハウスを支えるOpen Table Format

ユースケースごとに最適なDWHを使い分けたい場合、データレイクハウスへの移行は簡単ではありません。多くのDWHはデータを独自の形式で保持・管理しており、同じファイル形式でも解釈方法が異なるうえ、排他制御の仕組みもないため、相互運用ができません。異なるDWHで同じデータを処理するには、DWH間でデータを複製する必要があり、保管コストの増加や管理の複雑化を招きます。

この課題を解決するのが Open Table Format(OTF) です。データの管理層(Table Format)を共通化することで、同じデータレイクストレージ上のデータを異なるDWHから相互運用可能にします。

fig02_otf_layers.png

主要なOpen Table Formatの比較

一般的にOTFと呼ばれるものは、Apache Iceberg、Apache Hudi、Delta Lake の3種類です。OTF間の互換性はありません(OTFという共通規格があるわけではない点に注意)。近年はApache Icebergが主流になりつつあります。

項目 Apache Iceberg Apache Hudi Delta Lake
OSS公開年 2018年 2017年 2019年
開発元 Netflix Uber Databricks
OSSコミュニティ Apache Software Foundation Apache Software Foundation Linux Foundation
ライセンス Apache License 2.0 Apache License 2.0 Apache License 2.0
主な強み エンジン非依存/スキーマ・パーティション進化 行単位Upsert/増分・ストリーム処理 Spark・Databricksとの親和性

これらのOTFが登場する以前は、データレイク上のテーブル管理に Apache Hive がよく使われていましたが、データ更新の信頼性やテーブル構造の柔軟性に課題がありました(詳細は後述の「Apache Hiveからの移行」を参照)。

上記のOTFはいずれも、こうしたHiveの課題を解決するために開発されたテーブルフォーマットであり、Apache Hiveの後継としての側面もあります。

Apache Icebergの概要

Apache Icebergとは

Apache Icebergは、大規模な分析データ向けのオープンなテーブルフォーマットです。データレイク上での高度なテーブル管理と、複数のデータ処理エンジンによる相互運用を可能にします。

  • データレイクハウスを実現
    • データレイク上で、データウェアハウスに近い分析性能とACIDトランザクションを提供する
  • データストア間の相互運用を実現
    • 1つのストレージ上のデータを、複数のデータ処理エンジンやデータウェアハウス間で読み書き可能にする

主要なOSS、クラウドサービス、商用データ基盤の多くがIcebergをサポートしており、データレイクハウスのデファクトスタンダードとなりつつあります。

fig03_01_iceberg.png

Icebergの仕様と実装

Icebergはテーブルフォーマットの「仕様」と、その仕様で定義された機能を「実装」したライブラリを提供しています。

Icebergの機能はSQLを実行するデータ処理エンジン(Compute Engine)側に実装され、各データ処理エンジンがIcebergの仕様に従ってテーブルにアクセスすることで、トランザクションや同時実行制御を実現します。

  • Iceberg仕様(Specification)
    • Icebergテーブルの仕様(規約)を定義したものであり、SQLを実行するデータ処理エンジンや、テーブルを管理するカタログは、この仕様に従いデータを処理する
    • 最新の仕様はApache Iceberg Specificationを参照
  • Iceberg実装(Implementation)
    • Icebergの仕様で定義された機能を実装した各言語用のライブラリであり、多くのデータ処理エンジンやカタログはこれを組み込んで実装されている
    • 実装言語はJava / Python(PyIceberg) / Rust / Go / C++で、Javaは全仕様を実装しているが、他の言語では未実装の仕様もある
    • 各言語の実装状況はApache Iceberg Implementation Statusを参照

fig03_iceberg_mechanism.png

2026年9月16日現在、最新のIcebergテーブルフォーマット仕様はVersion 3(2025年5月仕様確定)、Java実装はVersion 1.11.0(2026年5月リリース)です。

Icebergの主要な機能

従来データレイク上のテーブル管理に活用されてきたApache Hiveよりも高度なデータ管理が可能です。

テーブルの管理:

  • スキーマ進化(Schema evolution)
    • テーブルのスキーマを変更できるため柔軟な運用が可能
    • 列の追加・削除・更新・名前変更・並べ替えをサポート
  • パーティションレイアウト進化(Partition layout evolution)
    • テーブルのパーティション分割に使用する列を変更可能
    • データ量やクエリパターンの変化に応じて、テーブルのレイアウトを更新
  • 隠しパーティショニング(Hidden partitioning)
    • 論理的なパーティションと物理的なディレクトリ構造のマッピングを自動的に管理
    • Hiveと異なり、ユーザはパーティション(ディレクトリ)の物理構造を意識する必要がない

テーブルのデータ操作:

  • トランザクション
    • 書き込み時のトランザクション分離レベルを選択可能(Snapshot isolationまたはSerializable isolation)
    • 読み出し時はコミット済みのレコードのみを参照可能(Snapshot isolation)
  • 行単位の差分更新
    • テーブルのレコードを行単位で更新可能であり、バッチ処理とニアリアルタイム処理の両方に対応可能

テーブルのスナップショット:

  • タイムトラベル(Time travel)
    • テーブルの変更履歴を保持しており、過去のコミット時点(スナップショット)に対するクエリが可能
  • ブランチ/タグ参照
    • ブランチ/タグによる特定スナップショットの参照が可能
  • 増分読み出し(Incremental read)
    • スナップショット間の追加差分のみを読み出し可能
  • ストリーミング読み出し(Streaming read)
    • 新規スナップショットを順次読み出し、ストリーム処理が可能
  • バージョンロールバック(Version rollback)
    • テーブルを過去のコミット時点(スナップショット)にロールバック可能

Icebergに対応したデータ処理エンジンとストレージ

多数のOSSと40以上のベンダの製品・サービスがIcebergテーブルをサポートしています。
Icebergをサポートしている主要なデータ処理エンジンとストレージを以下に示します。

対応するデータ処理エンジン:

分類 データ処理エンジン
OSS Spark / Flink / Trino / Presto / Hive / Impala / Kafka Connect / ClickHouse / DuckDB / StarRocksなど
商用製品 Teradata / Cloudera / Dremio / Starburst / Confluent / Hitachi Advanced Databaseなど
クラウド Amazon Redshift / Amazon Athena / Amazon EMR / Microsoft Fabric / Google BigQuery / Snowflake / Databricksなど

対応するストレージ:

分類 ストレージ
OSS Hadoop (HDFS) / Apache Ozone / Ceph (S3互換) / SeaweedFS (S3互換) など
商用製品 Dell EMC ECS / MinIO AIStor (S3互換) など
クラウド Amazon S3 / Azure Data Lake Storage / Google Cloud Storage / Alibaba Cloud Object Storage Serviceなど

Apache Icebergのユースケースとシステム構成例

Icebergの特徴を生かすことで、高機能で柔軟なデータ分析基盤を構築できます。

データメッシュ

マイクロサービスでは、各ドメインチームがそれぞれ業務用のRDBを持ちます。一方、分析用データはサイズが大きいため、集中型のデータウェアハウスでまとめて管理するのが一般的です。データメッシュは、こうした分析用データも各ドメインチームで分散管理していこう、という考え方です。

Icebergを導入すると、データを一か所に集めつつ、各ドメインチームが用途に適した分析ツールを使えるようになります。たとえば営業チームはBIツールやダッシュボードからSQLでアクセスし、AIチームはSparkやノートブックで機械学習モデルを構築できます。

CDCによるニアリアルタイム分析

分析クエリは大量のデータを読み込むため、業務用のRDBでそのまま実行するのは現実的ではありません。業務のトランザクション処理と分析クエリがリソースを奪い合うほか、RDBは並列分散処理ができず大量データの読み出しにも時間がかかります。

そのため一般的には、変更データキャプチャ(CDC: Change Data Capture)でデータをRDBからDWHへコピーし、DWH側で分析クエリを実行します。

Icebergは行単位の差分更新に対応し、CDCによるニアリアルタイムな同期が可能です。そのため、常に最新のデータにもとづいた分析ができます。ACIDトランザクションにより、CDCの書き込みと参照クエリの競合を気にする必要もありません。

機械学習データセット管理

機械学習モデルの構築では、画像・音声・テキスト・センサデータなどを前処理して訓練データを作ります。そのため、非構造データと構造データをどちらも扱えるデータレイクハウスが向いています。

I画像・音声などの非構造データはオブジェクトストレージ上のファイルとして管理します。前処理後の構造データやJSONなどの半構造データ(Variant型)は、Icebergテーブルとして扱えます。加えて、タイムトラベルやスナップショットで訓練データをバージョン管理でき、モデルの再現性を担保できます。

Apache Hiveからの移行

従来、データレイク上のテーブル管理には Apache Hive がよく使われてきました。HiveはHadoopの分散ファイルシステム(HDFS)を前提とし、テーブルとパーティションをディレクトリ構造で表現するシンプルな設計でしたが、それゆえに次のような弱点がありました。

  • ACIDトランザクションの保証が限定的で、複数エンジン間で一貫して利用できない
  • 行単位更新はORCトランザクショナルテーブルに限られ、性能・エンジン互換に制約がある
  • テーブルのスキーマやパーティションのレイアウトを後から変更できない

Icebergは、こうしたHiveの弱点を解消しています。ACIDトランザクションでデータの整合性を担保し、行単位の差分更新を可能にするとともに、スキーマ進化・パーティションレイアウト進化にも対応しています。

Icebergを活用したデータ分析システムの構成例

これまで紹介した機能を活用することで、以下のようなデータ分析システムを構築できます。

  • CDCによるニアリアルタイム分析:RDBの業務データ更新をDebeziumで捕捉してKafkaに取り込み、Kafka Iceberg ConnectorでIcebergテーブルへ同期する
  • データメッシュ:ビジネスチームはBIツールやダッシュボードからTrinoでSQL分析し、AIチームはSparkで生データから機械学習モデルを構築する
  • 訓練データのバージョン管理:スナップショットにより、機械学習モデルの再現性を担保する

fig04_usecase_system.png

Apache Icebergのアーキテクチャ

ここからは、Icebergテーブルが実際にどのようなファイルで構成され、それらがどう対応付けられているかを見ていきます。

Icebergの全体構成

Icebergテーブルは、大きく カタログ、メタデータ、実データ の3層で構成されます。

  • Icebergカタログ

    • 最新のメタデータの位置(ポインタ/ファイルパス)を保持
    • Iceberg RESTカタログ(任意)
      • カタログを操作するIceberg REST API仕様を実装したカタログサービスであり、認証認可などの拡張機能も実装可能
  • メタデータ

    • テーブルのスキーマ、更新履歴(スナップショット一覧)、統計情報などを保持
  • 実データ

    • 実データ、削除フラグを保持

これらのIcebergテーブル仕様に準拠したファイルを読み書きする機能を、データ処理エンジン側に実装します。

データ処理エンジンがIcebergテーブルを参照するときは、カタログ → メタデータ → データの順に辿ってテーブルのレコードを取得します。Icebergテーブルを更新するときは、データ → メタデータの順にファイルを作成し、カタログのポインタを切り替えて更新をコミットします。

fig05_overall_structure.png

Icebergテーブルの論理構造

Icebergのデータは Namespace → Table → Record(行) の階層構造で表現されます。Namespaceは階層化も可能です。

Table内のRecordは、Partitionに指定した列の値に応じて格納先ファイルが振り分けられます。Partitionには複数の列を指定することもできます。

fig06_logical_structure.png

Icebergテーブルの物理構造

メタデータ層で論理テーブル構造との対応付けを管理します。主要な構成要素は以下の通りです。

  • カタログ

    • 最新のメタデータファイルへのポインタ(ファイルパス)を保持し、テーブル更新時にポインタをアトミックに切り替えてトランザクションを実現
  • メタデータ

    • テーブルのメタデータ(Metadata File、JSON形式)
      • テーブルのスキーマ、Partition仕様、Manifest List (スナップショット) 一覧(更新履歴)などを保持
      • コミット(レコード群の追加・更新・削除)またはメタデータ更新(スキーマ・Partition変更など)ごとに新しいファイルを作成
    • テーブルのスナップショット(Manifest List、Avro形式)
      • ある時点のテーブル状態(スナップショット)を構成するManifest Fileの一覧、Partitionレベルの統計情報などを保持
      • コミットごとに新しいファイルを作成
    • テーブルのファイル情報(Manifest File、Avro形式)
      • テーブル更新で作成されたData FileまたはDelete Fileの一覧、列レベルの統計情報などを保持
      • コミットを構成するレコード群の追加・更新・削除ごとに新しいファイルを作成
  • 実データ

    • 追加データ(Data File、Parquet/ORC/Avro形式)
      • テーブルのレコードを保持
      • レコード群の追加・更新のたびに新しいファイルを作成
    • 削除データ(Delete File、Parquet/ORC/Avro形式(Deletion VectorはPuffin形式))
      • Data File内の削除対象のレコードを記録(Merge-on-Read時のみ作成)
      • レコード群の更新・削除のたびに新しいファイルを作成

fig08_metadata_before_update.png

Icebergテーブルに追加したRecordはData Fileに保存されます。Data FileのフォーマットはParquet/ORC/Avroから選択できます。削除したRecordについては、Merge-on-Readモード時にはDelete Fileに記録されます。

また、Partition列によって物理的にデータ範囲を分割することで、書き込みや読み出しを効率的に並列分散処理できます。

レコード更新時のファイル構成

Icebergはレコードの更新方法として Copy-on-Write(CoW) と Merge-on-Read(MoR) のいずれかを選択できます(詳細は後述)。

レコードを Merge-on-Read(MoR) で更新した場合、更新後のレコードを格納したData File、更新前のレコードの位置を記録したDelete File、およびこれらのファイルを参照する新しいメタデータファイルが作成されます。

既存のData Fileやメタデータファイルは不変であり、変更されません。更新前のテーブル状態(履歴)はスナップショットとして管理され、過去のスナップショットから参照されるファイルも保持されます。

fig09_metadata_after_update.png

ディレクトリ/ファイル配置

Icebergテーブルを構成するメタデータファイルと実データファイルは、任意のストレージ上に保存されます。ファイルの物理配置は実装により異なります。

一般的には、テーブルごとにディレクトリが作成され、ファイルは metadata ディレクトリと data ディレクトリに格納されます。

① テーブル store.products 作成後:

warehouse/
└── store/
    └── products/
        └── metadata/
            └── 00000-275436a1-...metadata.json    ★Metadata file追加

② レコード挿入後(INSERT):

warehouse/
└── store/
    └── products/
        ├── data/
        │   ├── category=drink/
        │   │   └── 00000-479-d2f9a8dd-...-00002.parquet    ★Data file追加
        │   └── category=food/
        │       └── 00000-479-d2f9a8dd-...-00001.parquet    ★Data file追加
        └── metadata/
            ├── 00000-275436a1-...metadata.json
            ├── 00001-3fd28d2d-...metadata.json    ★Metadata file追加
            ├── d3910c43-...-m0.avro    ★Manifest file追加
            └── snap-1954445999...-d3910c43-...avro    ★Manifest list (Snapshot) 追加

③ レコード更新後(UPDATE / Merge-on-Read):

warehouse/
└── store/
    └── products/
        ├── data/
        │   ├── category=drink/
        │   │   ├── 00000-479-d2f9a8dd-...-00002.parquet
        │   │   ├── 00000-492-add79e42-...-00002.parquet    ★Data file追加
        │   │   └── 00000-492-add79e42-...-00001-deletes.parquet    ★Delete File追加
        │   └── category=food/
        │       ├── 00000-479-d2f9a8dd-...-00001.parquet
        │       ├── 00000-492-add79e42-...-00001.parquet    ★Data file追加
        │       └── 00000-492-add79e42-...-00002-deletes.parquet    ★Delete File追加
        └── metadata/
            ├── 00000-275436a1-...metadata.json
            ├── 00001-3fd28d2d-...metadata.json
            ├── 00002-e868139e-...metadata.json    ★Metadata file追加
            ├── d3910c43-...-m0.avro
            ├── 60074f90-...-m0.avro    ★Manifest file追加
            ├── 60074f90-...-m1.avro    ★Manifest file追加
            ├── snap-1954445999...-d3910c43-...avro
            └── snap-6445932521...-60074f90-...avro    ★Manifest list (Snapshot) 追加

Apache Icebergのカタログ

Icebergカタログの概要

Icebergテーブルを構成する3層のうち、カタログはテーブルへの入口となる要素です。

Icebergカタログは、テーブルごとに最新のMetadata Fileへの参照(ファイルパス)を保持し、テーブル更新時(コミット時)にその参照をアトミックに切り替え(CAS: Compare-And-Swap)します。この基本機能については独立した仕様はなく、Metadata Fileへの参照の管理方法やアトミック更新の実現方法は、各カタログ実装に依存します。

Icebergでは、このカタログ操作をネットワーク経由で実行するための標準プロトコルとして、Iceberg REST Catalog Specという仕様を定義しています。REST Catalog SpecはOpenAPIベースであり、Namespace/Table/Viewの管理、コミット、認証などに関するAPIを定義しています。

カタログの実装には、基本機能をデータ処理エンジン側に実装したものと、プロトコル仕様も含めて独立した RESTカタログサービス として実装したものがあります。

項目 処理エンジン内蔵型カタログ RESTカタログ
カタログ操作 カタログのメタデータを任意のストレージやサービス(Hive Metastore、RDBMS、ファイルシステムなど)に保存して、処理エンジン側でカタログのメタデータを構築・更新する 処理エンジンはOpenAPIベースの標準的なREST APIでカタログサービスにアクセスし、カタログサービス側でカタログのメタデータを構築・更新する。
用途 開発・検証環境や、特定エンジンでアクセスする環境向き 本番環境や、複数エンジンでアクセスする環境向き

fig11_catalog_impl.png

Icebergカタログ選定時の注意点

カタログ間には互換性がないため、カタログの選択は慎重に検討する必要があります。 例えば、あるカタログで作成したテーブルを、別のカタログから読み出すことはできません。

また、処理エンジン内蔵型カタログは、処理エンジンによって対応可否が異なります。例えば、Hive Catalogを使用するエンジンはHiveクライアントを、Glue Catalogを使用するエンジンはAWS SDKを、それぞれ内蔵している必要があります。将来的に別の処理エンジンも利用する可能性がある場合は、RESTカタログの中から選択することを推奨します。

このような理由から、現在はRESTカタログが主流といえます。また、各カタログサービスが独自の機能拡張を提供する動きもみられます。

主要なカタログ実装

処理エンジン内蔵型カタログ実装

開発・検証環境や、特定のエンジンのみでアクセスする環境に向いています。

分類 実装 バックエンド・特徴
OSS JDBC Catalog PostgreSQL / MySQLなどのRDBMSに保存。小・中規模環境向け
OSS Hive Catalog Hiveメタストアに保存。既存Hive環境からの移行向け
OSS Hadoop Catalog ファイルシステムのディレクトリに保存。本番非推奨
OSS In-Memory Catalog メモリ上に保存。テスト用
OSS Nessie Catalog Nessieサーバに保存。RESTカタログも存在
商用製品 ECS Catalog Dell EMC ECSオブジェクトストレージに保存
クラウド Glue Catalog AWS Glueに保存。現在はRESTカタログを推奨
クラウド DynamoDB Catalog Amazon DynamoDBに保存
クラウド BigQuery Metastore Catalog Google BigQuery Metastoreに保存。現在はRESTカタログを推奨
クラウド Snowflake Catalog Snowflakeに保存。読み取り専用。現在はRESTカタログを推奨

RESTカタログ実装

本番環境や、複数エンジンからアクセスする環境に向いています。独自の拡張機能を備えたものが多いです。

分類 実装 特徴
OSS Apache Polaris Iceberg REST仕様のリファレンス的実装
OSS Unity Catalog Delta LakeとIcebergの両テーブル形式を管理
OSS Nessie Git風のブランチ / タグによるバージョン管理に対応。REST対応は実験的機能
OSS Apache Gravitino Iceberg以外(ファイル / Kafka / MLモデルなど)も統合管理
OSS Lakekeeper Rust実装による軽量・高性能なカタログ
クラウド AWS Glue Data Catalog AWSサービス(Athena / EMR / Redshift / Glue ETLなど)と統合可能
クラウド Amazon S3 Tables S3上のIcebergテーブル向けマネージドサービス
クラウド Google BigLake Metastore BigQuery / Spark / Trinoなど複数エンジンで相互運用可能
クラウド Snowflake Horizon Catalog PolarisベースのSnowflake向けカタログ

Apache Icebergの書き込み方式と性能設計

Icebergでは、テーブルプロパティを使用して書き込み方式やデータファイルの形式を設定できます。これにより、書き込み時にデータを整備して読み出し時の効率を高めるか、整備を抑えて書き込み速度を優先するかというトレードオフを調整できます。

主な設定項目を以下に示します。

  • 書き込みモード:write.[update|delete|merge].mode
  • 書き込み分散モード:write.distribution-mode
  • データファイルフォーマット:write.format.default

例えば、ストリーム処理では書き込み性能を、分析処理では読み出し性能を優先するなど、ユースケースに応じて設定を選択します。

また、書き込み時のトランザクション分離レベル(競合検出の厳密性)を選択することで、データ整合性と同時書き込み成功率のトレードオフを調整できます。

  • トランザクション分離レベル:write.[update|delete|merge].isolation-level

書き込みモード

Copy-on-WriteとMerge-on-Read

テーブルの書き込み操作は以下の4種類があります。

  • INSERT(追加)
  • UPDATE(更新)
  • DELETE(削除)
  • MERGE INTO(複数のINSERT/UPDATE/DELETEをまとめて実行)

このうちUPDATE/DELETE/MERGEでは、書き込みモードwrite.[update|delete|merge].modeに以下のいずれかを選択します。

  • Copy-on-Write(CoW): 書き込み時に、更新後の内容を反映した新しいData Fileを作成
  • Merge-on-Read(MoR):書き込み時は更新差分(Delete FileとData File)のみを作成し、読み出し時にマージして更新後の内容を復元

以下のSQLでIcebergテーブルのレコード2件をUPDATE(更新)する例を説明します。なお、これはSpark SQLとIcebergテーブルフォーマットv2における例です。

-- レコードを2件更新
UPDATE demo.store.products
SET price = CASE id
    WHEN 'F001' THEN 200   -- food: Apple
    WHEN 'F003' THEN 250   -- food: Orange
END
WHERE id IN ('F001', 'F003');

Copy-on-Write(CoW) でレコードをUPDATEした場合、以下のように更新後の全レコードを格納したData Fileを新規作成します。更新するレコード数にかかわらず、Data File全体の新規作成が必要となります。この方式は書き込み時の負荷は高いですが、読み出し時は少数のData Fileを参照するだけで済みます。

write_mode_CoW.png

Merge-on-Read(MoR) でテーブルのレコードをUPDATEした場合、更新後のレコードを追加するData Fileと、更新前のレコードを削除するDelete Fileを新規作成します。更新する差分だけ書き込めばよいため、書き込み時の負荷は低いですが、読み出し時は多数のData FileとDelete Fileを参照する必要があります。

write_mode_MoR.png

いずれの方式も既存のメタデータ/データファイルは書き換えず不変であり、新規にファイルを追加していきます。ファイルは更新のたびに増え続けるため、後述するメンテナンスタスクで定期的に削除または結合(コンパクション)する必要があります。

Copy-on-Write(CoW)とMerge-on-Read(MoR)の性能面での比較を以下に示します。

比較項目 Copy-on-Write(CoW) Merge-on-Read(MoR)
書き込み性能 × 更新後の内容を反映した新しいData Fileを都度作成 〇 更新差分のみのData File / Delete Fileを作成
読み出し性能 〇 少数のData Fileのみを参照 × 多数のData FileとDelete Fileを参照・マージ
適したユースケース 更新頻度が低く、読み取り性能を重視する分析処理 更新頻度が高く、書き込み性能を重視する処理

Delete Fileの種類

Merge-on-Read(MoR)で使用するDelete Fileには複数の種類があり、ワークロードに応じて最適なものを選択する必要があります。使用するDelete Fileは、書き込みモード・Icebergテーブルフォーマットのバージョン・処理エンジンなどから決定されます。

書き込み
モード
テーブルフォーマット
バージョン
主な処理エンジン Delete Fileの種類 想定ワークロード
CoW v1 / v2 / v3 Spark, Flink, Trinoなど なし 更新頻度が低いバッチ書き込み
(読み取り重視)
MoR v2 Spark, Flink, Trinoなど Position Delete File
・削除位置を記録
・事前に削除位置の特定が必要
更新頻度が低いバッチ書き込み
MoR v2 Flink CDC※など Equality Delete File
・削除条件を記録
・事前の削除位置特定が不要
ストリーミング書き込み
(UPSERT)
MoR v3 Sparkなど Deletion Vector (DV)
・ビットマップで削除位置を記録
・事前に削除位置の特定が必要
更新頻度が高いバッチ書き込み

※ FlinkのUPSERT処理では、条件によってEquality Delete FileとPosition Delete Fileの両方が生成される場合があります

なお、v2で導入されたPosition Delete FileとEquality Delete Fileは、いずれもv3で導入されたDeletion Vector (DV)への移行が進められています。

Position Delete File: v3でDeletion Vectorに移行済み

Icebergテーブルフォーマットv3のDeletion Vectorは、v2のPosition Delete Fileによる削除情報をより効率的に表現するために追加された方式です。v3テーブルでは、新規の位置ベースの削除情報はDeletion Vectorとして書き込まれます。

Position Delete Fileでは削除回数が増えるほどファイル数が増加し、読み出し時のマージが重くなるという課題がありました。Deletion Vectorは削除位置をRoaring Bitmapで表現し、1つのData Fileにつき最大1つのDeletion VectorをPuffinファイルに格納します。

これによりファイル数を抑制し、読み出し時の処理負荷を軽減できます。また、ビットマップは圧縮効率が高いためファイルサイズも抑えられます。

なお、Position Delete File自体が仕様から削除されるわけではなく、v2以前のテーブルとの互換性のため引き続き仕様に残ります。

Equality Delete File: v4でDeletion Vectorに移行予定

Icebergテーブルフォーマットv2のEquality Deleteは、削除対象レコードの条件のみを記録します。そのため事前のテーブルスキャンによる削除位置の特定が不要となり、書き込みコストが安いというメリットがあります。しかし、読み込み側はData Fileをスキャンして削除条件に一致する行を洗い出す必要があり、コストが読み手に転嫁されるという課題があります。

Equality Deleteは、CDCでIcebergテーブルに書き込む用途では有効ですが、CDCでIcebergテーブルから変更差分を読み出す場合や、各行の変更履歴を追跡するRow Lineageなどの機能とは相性が悪い点も課題とされてきました。これらの機能は、特定の行がいつ・どのように変更されたかをピンポイントで把握できることが前提です。しかしEquality Deleteの場合、ある行が実際に削除済みかどうかを判定するには、その行を含むData File全体を読み込み、削除条件と突き合わせる必要があります。

こうした背景から、Apache Icebergコミュニティでは2026年8月、現在策定中のv4仕様において新規のEquality Delete書き込みを禁止する提案が正式に可決されました([VOTE] Deprecate equality deletes in Iceberg V4 (forbid new writes), #17783)。既存のv2/v3テーブルおよびv4へアップグレードされたテーブルに残るEquality Deleteの読み込みは、引き続きサポートされます。

この移行を支えるため、FlinkではEquality Delete FileをDeletion Vectorへ変換するConvertEqualityDeletesというメンテナンスタスク(Flink上のバックグラウンドジョブとして動作)が実装されています。

書き込み分散モード

テーブルごとに、書き込み時の分散処理方式をwrite.distribution-modeで指定します。
この設定では、レコードをシャッフルおよびソートしてからファイルに書き込むか否かを制御します。

  • シャッフル処理
    • Partition単位でレコードを同一タスクに集約してから書き込むことで、生成されるファイル数を抑制
    • 参照時に読み出すファイル数が減るため、参照性能が向上
  • ソート処理
    • 指定した列の値でレコードをソートし、値の範囲ごとにまとめてファイルに書き込み
    • 参照時にファイルの統計情報(列の値のmin/max)から検索範囲外のファイルを判別してスキップ可能
    • ファイル内も列の値でソートされているため、効率的に検索可能

書き込み時の負荷が変わるほか、生成されるファイル数やファイル内の検索性が変わるため、読み出し時の性能に影響します。

分散モード シャッフル ソート 格納性能 参照性能 説明
none なし なし 〇 × レコードをそのまま書き込み
hash あり なし △ △ Partition単位でレコードを集めてから書き込み
range あり あり × 〇 Partition・ソート列の範囲でレコードを分配し、ソートしてから書き込み

なお、分散モードのデフォルト設定はIcebergのバージョンや処理エンジンによって異なります。

データファイルフォーマット

テーブルごとに、Data Fileのフォーマットをwrite.format.defaultで指定します。書き込み時の負荷、ファイル内のレコードの持ち方に影響するため、格納性能/参照性能/ファイルサイズ(ストレージ効率)に影響します。

フォーマット 格納配置 圧縮コーデック
(デフォルト)
格納性能 参照性能 ファイルサイズ
parquet
(デフォルト)
列指向 Zstandard × 〇 小
orc 列指向 Zlib × 〇 小
avro 行指向 gzip 〇 × 大

ParquetとORCはいずれも列指向フォーマットで、機能面はほぼ同等です。Parquetがデフォルトとして広く使われている一方、ORCは既存のHiveデータとの互換性維持が必要な場合に選択されます。

Avroは行指向フォーマットでレコード単位の書き込みに適しており、格納は高速ですが参照性能はParquet/ORCに劣るため、ストリーム処理など書き込み速度を優先する場面で使用されます。

行指向ファイルと列指向ファイルには以下の違いがあります。

fig12_row_vs_column.png

項目 行指向(Avro) 列指向(Parquet / ORC)
格納性能 〇 シーケンシャルに書き込み × 列単位に分割・圧縮してから書き込み
参照性能 × 必要な列だけの読み出しは非効率 〇 必要な列のみを効率的に読み出し可能
圧縮効率 × 異なる型が混在し圧縮効率が低い 〇 同じ型をまとめて効率的に圧縮し、I/O時間を短縮
検索性能(統計情報) × 統計情報によるファイル内のスキップは不可 〇 統計情報でグループ単位のスキップや列の絞り込みが可能

列指向ファイルは複数レコードの値を列単位でグループ化して格納するため、参照時は以下のメリットがあり高速に読み出し可能です。

  • 指定列のデータをまとめて高速に読み出せる
  • 同じ型の値をまとめて効率的に圧縮できるため、ファイルサイズが小さくなり読み出しサイズを抑えられる
  • 列単位の統計情報により、検索時に範囲外のファイルをスキップできる
  • 格納時に列をソートしておくことで、ファイル内の検索も高速化できる

一般的なデータ分析のクエリでは、ある列でフィルタやグループ化を行い、別の列の値を集計(合計や平均など)します。そのため、分析クエリでは列単位の処理を効率的に行える列指向ファイル形式が有利となります。

ただし、列単位の分割や圧縮処理が必要なため、格納時の書き込み性能は行指向ファイルより劣ります。そのため、ストリーム処理で書き込み速度を優先する場合は、行指向ファイルが有利といえます。

なおIcebergでは、行指向ファイル(Avro)で高速に書き込み、バックグラウンドのコンパクションで定期的に列指向ファイル(Parquet)へ変換するという組み合わせも可能です。

トランザクション分離レベル

Icebergは、複数の書き込みが同時に実行されてもテーブルの整合性を維持できるよう、トランザクション機能を提供しています。書き込み時(UPDATE / DELETE / MERGE)の競合検出の厳密性(トランザクション分離レベル)を、次のテーブルプロパティで指定します。

  • write.update.isolation-level
  • write.delete.isolation-level
  • write.merge.isolation-level

選択可能なトランザクション分離レベルは次の2つです。

  • serializable (Serializable Isolation、デフォルト設定)
  • snapshot (Snapshot Isolation)
項目 Serializable Isolation(デフォルト) Snapshot Isolation
競合検出 処理対象のData Fileに加え、処理開始後に追加されたData Fileも検証する 処理対象のData Fileのみ検証し、処理開始後に追加されたData Fileは検証しない
特徴 競合を厳密に検出する 同時書き込み時にコミットしやすい

Serializable Isolationはデータの整合性を重視し、Snapshot Isolationは同時書き込み時のコミットのしやすさを重視します。

基本的にはデフォルトのSerializable Isolationを使用し、高頻度の同時書き込みによるコミット失敗が頻発するような場合に、Snapshot Isolationへの変更を検討します。

なお、どちらの分離レベルでも、読み出し側は常にコミット済みのデータのみを参照します。

Apache Icebergの更新・参照処理の流れ

ここからは、具体的なシナリオに沿ってテーブルの更新・参照処理の流れを解説します。

シナリオ:

Spark SQLでIcebergテーブルのレコードを更新・参照します。Icebergテーブルのレコードを更新・参照するクエリ(SQL)を、Spark Thrift Server経由でSparkジョブに変換して実行します。

今回は現状多くのデータ処理エンジンが対応しているIceberg v2の利用を想定します。

テーブル設定:

  • 書き込みモード: Merge-on-Read(MoR)(write.[update|delete|merge].mode = merge-on-read)
    • Iceberg仕様バージョン: v2
    • データ処理エンジン: Spark
    • 削除ファイル: Position Delete File
  • 分散モード: Hash(write.distribution-mode = hash、シャッフルあり・ソートなし)
  • ファイルフォーマット: Parquet(write.format.default = parquet)

以下はSparkとIceberg v2を使用した場合の代表的な処理例であり、詳細な実行方法はデータ処理エンジンやバージョンによって異なります。

Icebergテーブルの更新処理の流れ

Spark SQLでレコードを更新する処理のステップを、図とともに示します。最初に「カタログ→メタデータ→データ」の順にファイルを辿って更新対象を把握し、その後「データ→メタデータ→カタログ」の順に新しいファイルを作成・コミットしていきます。

1. クエリ発行: SQLクライアントがSpark Thrift Serverに更新クエリ(UPDATE/MERGE)を発行する。
2. Sparkのジョブに変換: Spark Thrift Serverがクエリを解析し、Sparkジョブに変換して実行する。

fig13_01-02.png

3. 対象テーブルのカタログを参照: SparkアプリケーションのDriverがIcebergカタログにアクセスして、更新対象テーブルの最新のMetadata Fileを探す。

fig13_03.png

4. テーブルの最新メタデータを参照: Metadata Fileを読み出して、最新のスナップショットを示すManifest Listを探す。

fig13_04.png

5. 最新スナップショットのマニフェストリストを参照: Manifest Listを読み出して、スナップショットを構成するManifest Fileの一覧を探す。

fig13_05.png

6. 各マニフェストファイルを参照: スナップショットを構成する各Manifest Fileを読み出して、更新対象のレコードが保存されたData File群を探す。

fig14_06.png

7. Taskを生成して並列分散処理: Executor群を起動して、Data Fileを処理するTaskを生成する。write.distribution-mode=hash の場合、Partition値を基に書き込みデータをシャッフルし、同じPartitionのレコードが同じ書き込みタスク群に集約されるように分配する。
8. データファイルを参照: 各Taskが各PartitionのData Fileを読み出し、更新対象のレコードを把握する(スキャン)。

fig14_07-08.png

9. データファイルと削除ファイルを作成: 更新後のレコードを格納した新しいData Fileと、更新前のレコード位置を記録したDelete Fileを作成する。

fig14_09.png

10. メタデータの再読み込みとデータ競合の確認: 最新のメタデータを再度読み込み、処理開始時から他のトランザクションがコミットされていないか確認する。トランザクション分離レベル(Serializable/Snapshot)に基づき競合の有無を検証し、もし競合する場合はここで処理を中止し、クエリは失敗して終了する。中止した場合は、すでに書き込んだData File / Delete Fileはどのスナップショットからも参照されない孤立ファイル(Orphan files)となり、定期的なメンテナンスタスクで削除する必要がある。

fig14_10.png

11. マニフェストファイルを作成: Driverが各Taskから送られたData File群/Delete File群の情報を集約し、Manifest Fileを作成する。Data FileとDelete Fileは別々のManifest Fileに記録する。

fig14_11.png

12. マニフェストリスト(スナップショットファイル)を作成: 更新後のテーブルを構成するManifest File群を記録したManifest Listを作成する。

fig14_12.png

13. メタデータファイルを作成: テーブルのスナップショット一覧(更新履歴)を記録したMetadata Fileを作成する。

fig14_13.png

14. カタログのポインタを切り替え(コミット): ポインタを最新のMetadata Fileに切り替えてトランザクションをコミットする。他のクライアントからは、この時点で更新内容が見えるようになる。

fig14_14.png

15. クエリ結果を返信: SQLクライアントへクエリの実行結果を返す。

fig14_15.png

Icebergテーブルの参照処理の流れ

以下に、Spark SQLでレコードを参照する処理のステップを、図とともに示します。
Icebergテーブルのレコードを参照するクエリ(SQL)を、Spark Thrift Server経由でSparkジョブに変換して実行します。

1. クエリ発行: SQLクライアントがSpark Thrift Serverに対して参照(SELECT)クエリを発行する。
2. Sparkジョブに変換: Spark Thrift ServerがクエリをSparkジョブに変換する。

fig19_01-02.png

3. 対象テーブルのカタログを参照: SparkアプリケーションのDriverがIcebergカタログにアクセスして、参照対象テーブルの最新のMetadata Fileを探す。
4. テーブルの最新メタデータを参照: Metadata Fileを読み出して、最新のスナップショットを示すManifest Listを探す。

fig19_03-04.png

5. 最新スナップショットのマニフェストリストを参照: Manifest Listを読み出して、スナップショットを構成するManifest Fileの一覧を探す。Partitionレベルの統計情報から、対象外のManifest Fileを判定してスキップする。
6. 各マニフェストファイルを参照: スナップショットを構成する各Manifest Fileを読み出して、参照対象のレコードが保存されたData FileとDelete Fileを探す。列レベルの統計情報から、対象外のファイルを判定してスキップする。

fig19_05-06.png

7. Taskを生成して並列分散処理: Executor群を起動して、各ファイルを処理するTaskを生成する。デフォルト128MBを目安に、大きなData Fileは複数Taskに分割し、小さなData Fileは複数まとめて1つのTaskに割り当てる。
8. 削除ファイルを読み出し: 各TaskがDelete Fileを読み出し、削除済レコードの一覧を取得する。
9. データファイルを読み出し: 各TaskがData Fileのレコードを順次読み出し、削除済レコードと突き合わせて検索対象のレコードを探す。

fig19_07-09.png

10. 各Taskが読み出したレコードを返却: 各Taskの取得したレコードをDriverに集約する。
11. クエリ結果を返信: SQLクライアントへ取得したレコード群を返す。

fig19_10-11.png

参照処理では、メタデータの統計情報を活用した パーティションプルーニング(マニフェスト単位のスキップ)と データスキッピング(Data File単位のスキップ)により、無駄な読み出しを削減している点がポイントです。

Apache Icebergの運用管理

Icebergテーブルの運用管理には、以下の処理があります。

  • テーブル管理: テーブルの作成・削除・設定変更
  • スナップショット管理: ブランチ/タグの作成・削除、ロールバックなど
  • メンテナンスタスク: メタデータ/実データファイルの定期的な削除・結合

テーブル管理

テーブルの構造(スキーマやパーティション)を定義・変更する処理です。Icebergはスキーマやパーティションを後から変更できるため、運用開始後もデータ量やクエリパターンの変化に柔軟に対応できます。

処理 概要
テーブルの作成・削除 Icebergテーブルの新規作成・削除
スキーマ変更
(Schema evolution)
列の追加・削除・更新・名前変更・並べ替え
パーティション変更
(Partition evolution)
パーティション分割に使用する列の追加・変更・削除
テーブルプロパティ変更 書き込みモード(CoW/MoR)やファイルフォーマットなどの設定変更

これらの変更はメタデータ操作のみで完結し、(PURGEを伴う削除を除き)実データの書き換えを伴わないため、安全かつ高速にテーブル構造を進化させられます。

スナップショット管理

コミットごとに作成されるスナップショット(テーブルのある時点の状態)を操作する処理です。過去の状態への巻き戻しや、Git風のブランチ/タグ運用が可能です。

処理 概要
ブランチ/タグの作成・削除 特定のスナップショットに名前を付けて参照可能にし、データをバージョン管理
ロールバック 現在のスナップショットを過去の時点に戻し、データ破損時などに復旧
変更の取り込み
(cherry-pick)
特定のスナップショットの変更内容を現在のテーブルに取り込み、新しいスナップショットを作成。検証済みデータのみを本番へ反映するWrite-Audit-Publish(WAP)パターンなどで利用

これらの操作はメタデータ操作のみで完結し、実データのコピーを伴わないため、大規模テーブルでも高速に実行できます。

メンテナンスタスク

メタデータ/実データファイルは更新のたびに増え続けるため、定期的に削除または結合(コンパクション)する必要があります。

処理 概要
スナップショットの削除(expire_snapshots) 保持期間を過ぎたスナップショットをメタデータから除外し、参照されなくなったファイルを削除
孤立ファイルの削除(remove_orphan_files) どのメタデータからも参照されないファイルを削除
Manifest fileのコンパクション(rewrite_manifests) Manifest Fileを再構成し、メタデータ参照を効率化
Data fileのコンパクション(rewrite_data_files) 多数の小さなData Fileを結合し、参照性能を改善
Delete fileのコンパクション(rewrite_position_delete_filesなど) 増加したDelete Fileを結合

これらのメンテナンス処理を定期的に実行することで、クエリ性能の劣化や不要なストレージ消費を防ぐことができます。特にMoRで運用する場合は、Delete Fileが蓄積して読み出し性能が低下しやすいため、コンパクションが重要になります。

コンパクションは対象ファイルの読み込みと再書き込みを伴うため、大規模なテーブルでは処理が重くなります。実行するタイミングや対象範囲(パーティション単位での実行など)を考慮し、業務への影響が少ない時間帯に実施することが望ましいです。

Apache Icebergのクイックスタート

クイックスタートの概要

Iceberg公式のQuickstartには、ローカル環境で試せるサンプルが用意されており、手元のDocker環境でIcebergのカタログ操作・テーブル作成・SQL実行・ファイル構造の確認までを一通り体験できます。

クイックスタートはIceberg RESTカタログ、Sparkクラスタ(Iceberg対応データ処理エンジン)、MinIO(S3互換ストレージ)で構成され、ノートブック/CLIからSQL/Icebergコードを実行して操作できます。

fig23_quickstart.png

クイックスタートはdocker-composeで以下のコンテナイメージを組み合わせて起動します。

コンテナ 役割
tabulario/spark-iceberg SparkとJupyter Notebook。ノートブック/CLIからSQL/SparkのIcebergコードを実行
apache/iceberg-rest-fixture Iceberg REST Catalog Adapter。インメモリのSQLiteをJDBCカタログとして利用
minio/minio MinIO(S3互換ストレージ)。メタデータ/データファイルを保持。オブジェクトブラウザ画面からファイルを参照
minio/mc MinIO Client。初期化時のバケット作成やCLIからのファイル参照に使用

クイックスタートの環境構築

クイックスタートの実行に必要な以下を用意しておきます。

クイックスタートの起動

docker-compose.ymlファイルを配置したディレクトリに移動し、Docker Composeでクイックスタートを起動します。

# Icebergクイックスタートを起動
docker-compose up

Spark SQLでIcebergテーブルを操作

以下のテーブルを作成してレコードを更新してみます。

fig24_table.png

#  Sparkセッションを開始
docker exec -it spark-iceberg spark-sql

1. Icebergテーブルを作成

-- ネームスペースが存在しない場合は作成
CREATE DATABASE IF NOT EXISTS demo.store;

-- テーブルが存在する場合は削除(PURGEでファイルごと削除して初期化)
DROP TABLE IF EXISTS demo.store.products PURGE;

-- テーブルを作成(書き込みモードはMoRを指定)
CREATE TABLE demo.store.products (
    category  string,
    id   string,
    name string,
    price     int
)
USING iceberg
PARTITIONED BY (category)
TBLPROPERTIES (
    'write.update.mode' = 'merge-on-read',
    'write.delete.mode' = 'merge-on-read',
    'write.merge.mode'  = 'merge-on-read'
);

2. Icebergテーブルにレコードを挿入

-- サンプルデータを投入
INSERT INTO demo.store.products VALUES
    ('food',  'F001', 'Apple',   120),
    ('food',  'F002', 'Banana',   80),
    ('food',  'F003', 'Orange',  150),
    ('food',  'F004', 'Grape',   300),
    ('food',  'F005', 'Melon',   500),
    ('drink', 'D001', 'Coffee',  200),
    ('drink', 'D002', 'Tea',     180),
    ('drink', 'D003', 'Water',   100),
    ('drink', 'D004', 'Juice',   150),
    ('drink', 'D005', 'Cola',    130);

-- データ確認
SELECT * FROM demo.store.products ORDER BY category, id;
-- drink   D001    Coffee  200
-- drink   D002    Tea     180
-- drink   D003    Water   100
-- drink   D004    Juice   150
-- drink   D005    Cola    130
-- food    F001    Apple   120
-- food    F002    Banana  80
-- food    F003    Orange  150
-- food    F004    Grape   300
-- food    F005    Melon   500
-- Time taken: 0.285 seconds, Fetched 10 row(s)

-- パーティションごとの件数
SELECT category, count(*) AS record_count
FROM demo.store.products
GROUP BY category
ORDER BY category;
-- drink   5
-- food    5
-- Time taken: 0.347 seconds, Fetched 2 row(s)

3. Icebergテーブルのレコードを更新

-- サンプルデータを更新
MERGE INTO demo.store.products AS t
USING (
    VALUES
        ('F001', 200),   -- food:  Apple
        ('F003', 250),   -- food:  Orange
        ('D001', 350),   -- drink: Coffee
        ('D004', 400)    -- drink: Juice
    AS s(id, price)
)
ON t.id = s.id
WHEN MATCHED THEN UPDATE SET t.price = s.price;

-- 更新後のテーブルを確認
SELECT * FROM demo.store.products ORDER BY category, id;
-- drink   D001    Coffee  350
-- drink   D002    Tea     180
-- drink   D003    Water   100
-- drink   D004    Juice   400
-- drink   D005    Cola    130
-- food    F001    Apple   200
-- food    F002    Banana  80
-- food    F003    Orange  250
-- food    F004    Grape   300
-- food    F005    Melon   500
-- Time taken: 0.416 seconds, Fetched 10 row(s)

MinIOのファイルを確認

MinIOに保存されたIcebergテーブルのファイルをMinIO ClientのCLIで確認してみます。
MinIOのオブジェクトブラウザ (http://localhost:9001/) から確認することも可能です。

# mcコンテナに入る
docker exec -it mc /bin/sh

# バケット内のファイルを表示
mc ls --recursive minio/warehouse
## [2026-09-01 07:59:45 UTC] 1.2KiB STANDARD store/products/data/category=drink/00000-479-d2f9a8dd-f9e5-4868-91f5-8937ecbe82fe-0-00002.parquet
## [2026-09-01 08:00:56 UTC] 1.5KiB STANDARD store/products/data/category=drink/00000-492-add79e42-b576-4829-aca7-582f6231e4a1-00001-deletes.parquet
## [2026-09-01 08:00:56 UTC] 1.2KiB STANDARD store/products/data/category=drink/00000-492-add79e42-b576-4829-aca7-582f6231e4a1-00002.parquet
## [2026-09-01 07:59:45 UTC] 1.2KiB STANDARD store/products/data/category=food/00000-479-d2f9a8dd-f9e5-4868-91f5-8937ecbe82fe-0-00001.parquet
## [2026-09-01 08:00:56 UTC] 1.2KiB STANDARD store/products/data/category=food/00000-492-add79e42-b576-4829-aca7-582f6231e4a1-00001.parquet
## [2026-09-01 08:00:57 UTC] 1.5KiB STANDARD store/products/data/category=food/00000-492-add79e42-b576-4829-aca7-582f6231e4a1-00002-deletes.parquet
## [2026-09-01 07:59:08 UTC] 1.0KiB STANDARD store/products/metadata/00000-275436a1-7a9f-4028-b10b-198238d0db7c.metadata.json
## [2026-09-01 07:59:45 UTC] 2.0KiB STANDARD store/products/metadata/00001-3fd28d2d-6760-46b6-83dc-1a0fe771cbee.metadata.json
## [2026-09-01 08:00:57 UTC] 3.0KiB STANDARD store/products/metadata/00002-e868139e-0ec8-4e94-b473-927b73c86f7e.metadata.json
## [2026-09-01 08:00:57 UTC] 7.3KiB STANDARD store/products/metadata/60074f90-090f-4ed8-be34-d04f94759c0a-m0.avro
## [2026-09-01 08:00:57 UTC] 7.3KiB STANDARD store/products/metadata/60074f90-090f-4ed8-be34-d04f94759c0a-m1.avro
## [2026-09-01 07:59:45 UTC] 7.3KiB STANDARD store/products/metadata/d3910c43-5519-404c-80ed-a4f91c6bb9b0-m0.avro
## [2026-09-01 07:59:45 UTC] 4.4KiB STANDARD store/products/metadata/snap-1954445999108493645-1-d3910c43-5519-404c-80ed-a4f91c6bb9b0.avro
## [2026-09-01 08:00:57 UTC] 4.4KiB STANDARD store/products/metadata/snap-6445932521924284814-1-60074f90-090f-4ed8-be34-d04f94759c0a.avro

Jupyter Notebookの利用

Jupyter Notebook (http://localhost:8888/) から事前に用意された各種ノートブックにアクセス可能です。JavaやPySparkコードによるIcebergの操作方法を確認できます。

おわりに

本記事では、Apache Icebergについて、その背景から概要、ユースケース、内部アーキテクチャ、更新・参照処理の流れ、メンテナンスタスク、クイックスタートの構成までを解説しました。

Icebergは、低コストなデータレイクストレージ上でデータウェアハウス相当の分析性能とACIDトランザクションを実現します。複数のデータ処理エンジン間での相互運用も可能にし、データレイクハウスのデファクトスタンダードとなっています。行単位の差分更新・スキーマ進化・タイムトラベルといった高度な機能を備え、CDCによるニアリアルタイム分析や、機械学習データのバージョン管理など、幅広いユースケースに対応できます。

Icebergの仕様やエコシステムは活発に進化を続けており、現在はIcebergテーブルのフォーマットバージョン4(v4)の策定が進んでいます。v4では、相対パスの採用によるテーブル移動の容易化(ポータビリティ向上)が予定されているほか、メタデータ構造の改善によるコミット処理の効率化、Column Families導入による列更新の効率化などが検討されています。

本記事が、Icebergを用いたデータレイクハウス構築の第一歩として参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?