データ基盤
オープンテーブルフォーマットとは:版をログで差し替える仕組み
- オープンテーブルフォーマット
- データ基盤
- レイクハウス
- Delta Lake
- Apache Iceberg
- Apache Hudi
- オブジェクトストレージ
- トランザクションログ
- スナップショット
- タイムトラベル
- スキーマ進化
- コンパクション
- カタログ
- Copy-on-Write
- Merge-on-Read
- Netflix
- Uber
- Airbnb
- Databricks
- Snowflake
目次
データレイクでは、テーブルはディレクトリの中に置いたファイルの集まりにすぎなかった。テーブルを読む処理はディレクトリの中のファイルの一覧を取り、そこに並ぶファイルを全部読む。保存と計算を分けたクラウドの分析では、そのファイルを安いオブジェクトストレージに置く。
オブジェクトストレージは、ファイルを丸ごと書き、名前で取り出す、安くて壊れにくい保存先である。この形には、データベースなら当然にできることが欠けていた。ある利用者の記録をテーブルから消すには、複数のファイルを書き換える必要がある。書き換えの途中で別の人がテーブルを読むと、一部のファイルだけが新しい状態を読んでしまう。書き換えが途中で失敗すると、テーブルは壊れた状態で残る。ファイルの数が数百万になると、一覧を取るだけで長い時間がかかる。一方で、データを一つの製品の独自の形式に入れれば、ほかのツールからは直接は読めなくなる。
この回は、誰でも読める形式のファイルを保ったまま、その上にデータベースのテーブルとしての性質を足す設計の話である。オブジェクトストレージに置いたデータレイクのファイルの集まりを、独自の形式に閉じ込めずに更新できるテーブルにする、という続きにあたる。本稿は、三つのオープンテーブルフォーマットの論文・仕様・開発元の記事、その比較を測った二つの論文、利用企業の公開記事を例に取る。
オープンテーブルフォーマットは、オブジェクトストレージ上のファイルの集まりを、どうやって安全に更新できるテーブルにするのか。そして何が解けずに残ったのか。
オープンテーブルフォーマットは、どのファイルがテーブルのどの版に属するかを記録し、その記録を不可分に差し替えることで、オブジェクトストレージ上のファイルに更新と過去の版を持たせたが、ファイルの整理とカタログの課題は残った。 テーブルを読む処理は、ディレクトリの一覧ではなく記録を読むので、変更の前か後かのどちらか一方だけを見る。古い記録とファイルを残しておけば、前の版も読める。一方で、ファイルが細かく増えれば、定期的にまとめ直すコンパクションが要る。さらに、テーブルごとに最新の記録の場所を持ち、差し替えの成否を判定する外部のサービス(カタログ)をどの会社の仕組みにするかが、新しい争点になった。
3 個のファイルのテーブルから、ある利用者の記録を消す
※ この節の数値は説明のための仮定で、測定値ではありません。
あるテーブルが、A・B・C の 3 個のファイルでできており、それぞれに 100 行、合計 300 行が入っているとする。これをテーブルの版 1 と呼ぶ。ある利用者の行が A に 2 件、C に 3 件あり、これを消したい。ファイルは書き換えられないので、その利用者の行を除いた新しいファイル A′(98 件)と C′(97 件)を書く。正しい結果は 295 件である。
ディレクトリの一覧でテーブルを表す場合、A′ を書いて A を消した直後に別の人がテーブルを読むと、一覧には A′・B・C が並ぶ。この人は 298 件を数え、C に残った 3 件を含む途中の状態を読む。A を消す前に読めば、A と A′ の両方が並び、398 件を数える。
記録でテーブルを表す場合は、版 1 を「A・B・C」、版 2 を「A′・B・C′」と書いた記録を持つ。書き手は A′ と C′ を書き終えてから、版 2 の記録を一回で書く。テーブルを読む人は最新の記録を見てからファイルを読むので、版 1 か版 2 のどちらかの全体だけを見る。A と C を消さずにおけば、版 1 を指定して前の状態も読める。
さらに、二人の書き手が同時に版 1 をもとに変更を作り、どちらも版 2 の記録を書こうとしたとする。記録の書き込みは「まだ誰も書いていなければ書く」という形で行うので、成功するのは一方だけである。もう一方は最新の版 2 を読み直し、自分の変更を版 3 として作り直す。
この例は、三つのことを示す。
- テーブルの中身は「どのファイルを含むか」を書いた記録で決まり、その記録を一回で差し替えれば、読む人は変更の前(300 件)か後(295 件)かのどちらかしか見ない。
- 古い記録とファイルを消さずに残す限り、前の版を読める。
- 二人が同じ次の版を同時に作ろうとすると、一方だけが成功し、他方はやり直す。
ディレクトリをテーブルとみなすと、一覧は遅く、変更は途中で見える
Databricks の Armbrust らは 2020 年の Delta Lake の論文で、オブジェクトストレージにファイルを置いただけのテーブルの問題を挙げた1。複数のファイルの更新は不可分ではないので、読む人は書き換えの途中を見る。更新の処理が途中で止まると、テーブルは壊れた状態で残る。さらに、S3 の一覧の取得は一回で最大 1,000 件しか返さず、一回に数十から数百ミリ秒かかるので、数百万のファイルを順に一覧するには数分かかる。論文の時点では S3 の一覧の結果が遅れて反映されることもあったが、S3 は 2020 年 12 月に、書いた直後から一覧に反映される形に改められた2。
Netflix が Apache ソフトウェア財団に出した Iceberg の提案書も、同じ弱点を前提にしている3。提案書は、オブジェクトストレージには結果の反映の遅れ、ディレクトリの一覧の遅さ、名前の変更ができないこと、フォルダの階層が無いことがあると書く。Netflix の時系列の計測データのテーブルは、1 か月分が 2,688 のパーティションに分かれた 270 万個のファイルでできていた。このテーブルを Hive のテーブルとして問い合わせると、実行の計画を立てるだけで 9.6 分かかった(Netflix の初期の測定)。
利用企業の記録もある。Airbnb は 2022 年の記事で、Hive のテーブルのパーティションが増えるにつれ、パーティションの情報を管理するデータベースの負荷が問題になったと書いた4。同じ記事は、エンジンごとにスキーマ変更の扱いが違ったので、スキーマを変えるとほぼ毎回、データの品質の問題が起きるか、費用のかかる書き直しが必要になったとも書いている。
テーブルの版を一つのメタデータで切り替えると、変更は全部か無かになる
オープンテーブルフォーマットとは、Parquet のような誰でも読める形式のデータのファイルはそのままにして、どのファイルがテーブルのどの版に属するかを管理用の記録(ログやメタデータ)に書き、その記録を不可分に差し替えることでテーブルを更新する決まりのことである。代表的なものに Delta Lake・Apache Iceberg・Apache Hudi がある。
Delta Lake の考え方は、どのファイルがそのテーブルに属するかを、オブジェクトストレージの中に置いたトランザクションログ(変更の記録を順に積んだもの)で管理することである1。ログは番号を振ったファイルの並びで、変更を確定させるには、次の番号のログのファイルを「まだ誰も書いていなければ」書く。この書き込みが成功した時点で、変更は全部まとめて確定する。現在の Delta の仕様も、ログのファイル一つ一つがテーブルの不可分な変更の単位だと定めている5。データのファイルもログも書き換えないので、前の版のテーブルを読むタイムトラベルもできる。ただし論文の時点の S3 には「まだ無ければ書く」という操作が無く、Databricks は自社のサービスで、同じ番号のログを一人だけが書けるようにする別の仕組みを使っていた。S3 は 2024 年 8 月に、この操作に当たる条件付きの書き込みを加えた6。
Delta Lake の論文は、この形の効果を測っている1。3,300 万行の小さなテーブルを 1,000 から 100 万のパーティションに分け、16 台の機械で全行を合計する問い合わせを流した。別の会社が提供する Hive は 1 万のパーティションのテーブルでファイルを見つけるのに 1 時間を超え、Delta Lake は 100 万のパーティションでも 108 秒だった。比べたエンジンは製品ごとに違い、テーブルの形式だけの差ではない。ただし同じ Databricks のエンジンでも、ログを使わない Parquet のテーブルは 10 万のパーティションで 450 秒かかった。
Apache Iceberg も、ディレクトリではなく個々のファイルを記録で管理する7。テーブルの状態は管理用のファイル(メタデータファイル)に書かれ、ある時点のテーブルの版(スナップショット)がどのファイルからなるかを記録する。変更のたびに新しいメタデータファイルを作り、テーブルが指す先を古いものから新しいものへ一回で差し替える。差し替えの前に別の変更が確定していれば、書き手は最新の版をもとに作り直す。Iceberg の仕様は、列を名前ではなく番号で追うと定めている。そのため、列の名前や順序を変えても(スキーマ進化)、それ以前に書いたファイルは正しく読める。先の Netflix の提案書によれば、Iceberg のテーブルでは、計画はパーティションによる絞り込みだけで 10 秒(問い合わせ全体は 13 分)、ファイルごとの最小値と最大値による絞り込みも使うと 25 秒(同 42 秒)だった3。これらは Netflix 自身の初期の測定である。
Apache Hudi は、Uber が 2017 年に発表した8。Hudi も、変更の確定を時系列の記録(タイムライン)に書き、行の更新をファイルの集まりに反映させる。Uber は 2018 年の記事で、Hudi を使って、テーブル全体を取り込み直す方式から変わった分だけを取り込む方式に移り、データが使えるようになるまでの遅れを 24 時間から 1 時間未満に縮めたと書いた9。これは HDFS 上の自社報告で、同じ時期に Marmaray という取り込みの仕組みも入れている。
Databricks の研究者は 2021 年の論文で、オブジェクトストレージの上にこうした記録の層を置き、データベースの機能を持たせたシステムをレイクハウスと呼んだ10。論文は、商用のデータウェアハウスがデータを独自の形式に閉じ込めると批判し、レイクハウスでは誰でも読める形式のファイルを直接読めると主張する。著者は全員 Databricks に属し、自社の方向を説明する立場にある。
更新の費用を、書き手と読み手のどちらが払うかを選ぶ
ファイルを書き換えずに行を更新する方法は、二つに分かれる。Hudi の文書は、これを Copy-on-Write と Merge-on-Read と呼ぶ11。Copy-on-Write は、更新のたびに対象の行を含むファイルを丸ごと書き直すので、読むときの手間は増えないが、少しの行を変えるだけでも書き込みが重くなる。Merge-on-Read は、変更を小さな記録のファイルに書いておき、読むときに元のファイルと合わせるので、書き込みは速いが、読むたびに合わせる手間がかかる。後で記録を元のファイルに取り込む作業(コンパクション)をしないと、読む手間は増え続ける。Delta Lake も、消した行を別の記録で示し、読むときに飛ばす仕組みを仕様に加えている5。
Jain らは 2023 年の論文で、三つの形式を同じ条件で比べた12。Hudi では、Merge-on-Read のテーブルへの行の更新は Copy-on-Write より 1.3 倍速かったが、更新後の問い合わせは 3.2 倍遅かった。一方、Iceberg 0.14 の Merge-on-Read は更新が 1.4 倍速く、この実験では更新後の問い合わせの速さはほぼ変わらなかった。ただし同じ論文の別の実験では、Iceberg 1.1.0 の Merge-on-Read も更新後の読み込みが大きく遅くなり、約 1 万行の変更で Copy-on-Write より遅くなった。この論文の著者には Databricks の研究者が含まれる。測定は各形式の 2022 年時点の既定の設定によるが、最初の実験の Iceberg だけは接続の上限を増やして測った。その実験では新しい 1.1.0 の Merge-on-Read がタイムアウトを繰り返したので、0.14 で代えている。
それでも、ファイルの整理と、メタデータの在りかを握るカタログは残る
記録を差し替える設計は、ファイルの整理を不要にしない。Iceberg の文書は、古い版の記録は消すまで溜まり続けるので定期的に期限切れにすることと、小さなファイルが多いと管理用の情報が増え、ファイルを開く費用で問い合わせが遅くなることを書いている13。Microsoft の研究者は 2024 年の論文で、TPC-DS(分析の性能を比べる業界標準の測定)の問い合わせと更新を、Spark の上で、間に整理の作業を挟まずに二回続けて流した14。二回目の所要時間は一回目より、Delta Lake で 92%(2.7 時間から 5.2 時間)、Iceberg で 45% から 73% 長くなった。Hudi は 5% から 6% しか延びなかったが、一回目から Copy-on-Write で 6.2 時間、Merge-on-Read で 23 時間かかっていた。著者らは、性能のよい形式でも時間とともに大きく遅くなりうると書いている。同じ論文は、性能と費用はエンジンや整理の進め方にも大きく左右されるとも述べる。この測定は、公式の監査を受けていない。
書き込みの回数にも上限がある。Delta Lake の論文は、オブジェクトストレージへの書き込みには数十から数百ミリ秒かかるので、一つのテーブルへの変更は一秒あたり数回しか確定できないと書いたが、当時の利用にはほぼ十分で、ログへの書き込みを仲介する仕組みで速くできるとも書いた1。2023 年の Jain らの論文は、同時に多くの書き込みを高い頻度でこなせるかを、未解決の問いとして挙げている12。変更を不可分にできるのは、一つのテーブルの中だけである1。
もう一つの課題は、テーブルが指す先を差し替える場所である。Iceberg の仕様は、ファイルシステムだけで差し替える方式をオブジェクトストレージでは安全でないとして廃止の予定にし、残る方式として、データベースなどに置いたポインタを確かめながら書き換える形を示している7。つまり、テーブルの最新の版を決めるのは、ファイルの外にあるカタログである。Delta の仕様にも、カタログを変更の成否の判定役にする方式が加わった5。
2024 年 6 月、このカタログをめぐって二つの会社が続けて動いた。Snowflake は Iceberg 用のカタログ Polaris を発表して 90 日以内のソースコードの公開を予告し、エンジンとカタログの間の制約が、オープンな標準の価値を損なう囲い込みを生んでいると書いた15。Databricks は自社のカタログ Unity Catalog のソースコードを公開し、Iceberg のカタログの API にも対応させた16。同じ月に Databricks は、Iceberg の作者らが作った会社 Tabular の買収を発表し、Delta Lake と Iceberg はどちらも Parquet を土台に似た設計を持ちながら、別々に開発されたことで互換性を失ったと書いた。同じ記事は、三つの形式のあいだの互換性を持たせる Delta Lake UniForm を対策に挙げ、Iceberg の元のチームを迎えてその範囲を大きく広げるとした17。Unity Catalog は公開の時点で Linux Foundation の傘下の LF AI & Data に置かれ16、Polaris は 2024 年 8 月に Apache ソフトウェア財団のインキュベータに入って、2026 年 2 月に正式なプロジェクトになった18。カタログのソースコードが財団の下に置かれても、オープンなファイルの形式の上でテーブルの最新の版をどの会社のカタログで決めるかは、各社の争点として残った。
出典18件
-
Armbrust ほか「Delta Lake: High-Performance ACID Table Storage over Cloud Object Stores」PVLDB 13(12), 2020. https://www.vldb.org/pvldb/vol13/p3411-armbrust.pdf — 素のファイルの問題、ログの設計、パーティション数の測定、書き込み回数の上限(Databricks)。 ↩ ↩2 ↩3 ↩4 ↩5
-
Amazon Web Services「Amazon S3 now delivers strong read-after-write consistency automatically for all applications」2020. https://aws.amazon.com/about-aws/whats-new/2020/12/amazon-s3-now-delivers-strong-read-after-write-consistency-automatically-for-all-applications/ — 一覧の操作も含む強い整合性。 ↩
-
Apache Incubator「Iceberg Proposal」2018. https://cwiki.apache.org/confluence/display/INCUBATOR/IcebergProposal — オブジェクトストレージの弱点と Netflix の初期の測定。 ↩ ↩2
-
Zhu ほか「Upgrading Data Warehouse Infrastructure at Airbnb」Airbnb Tech Blog, 2022. https://web.archive.org/web/2023/https://medium.com/airbnb-engineering/upgrading-data-warehouse-infrastructure-at-airbnb-a4e18f09b6d5 — パーティションの管理の負荷とスキーマ変更の問題(自社報告)。 ↩
-
Delta Lake Project「Delta Transaction Log Protocol」2026年10月7日取得. https://github.com/delta-io/delta/blob/master/PROTOCOL.md — ログのファイルが変更の単位、消した行の記録、カタログ管理のテーブル。 ↩ ↩2 ↩3
-
Amazon Web Services「Amazon S3 now supports conditional writes」2024. https://aws.amazon.com/about-aws/whats-new/2024/08/amazon-s3-conditional-writes/ — 無ければ書く条件付きの書き込みの追加。 ↩
-
Apache Iceberg「Iceberg Table Spec」2026年10月7日取得. https://iceberg.apache.org/spec/ — ファイル単位の記録、ポインタの差し替え、列番号、ファイルシステム方式の廃止予定。 ↩ ↩2
-
Rajaperumal, Chandar「Hudi: Uber Engineering’s Incremental Processing Framework on Apache Hadoop」Uber Engineering, 2017. https://www.uber.com/blog/hoodie/ — タイムラインへの記録による変更の確定と行の更新。 ↩
-
Shiftehfar「Uber’s Big Data Platform: 100+ Petabytes with Minute Latency」Uber Engineering, 2018. https://www.uber.com/blog/uber-big-data-platform/ — Hudi による差分の取り込みで遅れを24時間から1時間未満に(自社報告)。 ↩
-
Armbrust ほか「Lakehouse: A New Generation of Open Platforms that Unify Data Warehousing and Advanced Analytics」CIDR, 2021. https://www.cidrdb.org/cidr2021/papers/cidr2021_paper17.pdf — レイクハウスの定義と独自形式への批判(全員 Databricks)。 ↩
-
Apache Hudi「Table & Query Types」2026年10月7日取得. https://hudi.apache.org/docs/table_types — Copy-on-Write と Merge-on-Read の違い。 ↩
-
Jain ほか「Analyzing and Comparing Lakehouse Storage Systems」CIDR, 2023. https://www.cidrdb.org/cidr2023/papers/p92-jain.pdf — Merge-on-Read の更新と後の問い合わせ、変更の大きさを変えた実験、書き込み頻度(Databricks の研究者を含む)。 ↩ ↩2
-
Apache Iceberg「Maintenance」2026年10月7日取得. https://iceberg.apache.org/docs/latest/maintenance/ — 古い版の期限切れと小さなファイルの影響。 ↩
-
Camacho-Rodríguez ほか「LST-Bench: Benchmarking Log-Structured Tables in the Cloud」Proc. ACM Manag. Data 2(1), 2024. https://arxiv.org/abs/2305.01120 — 整理なしの二回目の遅れ、3形式の5構成(Spark、Microsoft、監査なし)。 ↩
-
Snowflake「Introducing Polaris Catalog: An Open Source Catalog for Apache Iceberg」2024. https://www.snowflake.com/en/blog/introducing-polaris-catalog/ — カタログとエンジンの制約が囲い込みを生むという主張(開発元)。 ↩
-
Databricks「Open Sourcing Unity Catalog」2024. https://www.databricks.com/blog/open-sourcing-unity-catalog — カタログの公開と Iceberg の API への対応、LF AI & Data への設置(開発元)。 ↩ ↩2
-
Databricks「Databricks Agrees to Acquire Tabular」2024. https://www.databricks.com/blog/databricks-tabular — Delta Lake と Iceberg が互換性を失ったという説明と、対策としての UniForm(開発元)。 ↩
-
Apache Incubator「Polaris Project Incubation Status」2026年10月7日取得. https://incubator.apache.org/projects/polaris.html — 2024年8月のインキュベータ入りと2026年2月のトップレベルプロジェクトへの昇格。 ↩
この記事はAIが執筆しています。内容には誤りが含まれる可能性があります。ご注意ください。