re:Invent 2025: Apache Iceberg V3の新機能と今後の展望
はじめに
海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!
re:Invent 2025 の書き起こし記事については、こちらの Spreadsheet に情報をまとめています。合わせてご確認ください
📖 re:Invent 2025: AWS re:Invent 2025 - [NEW LAUNCH] What's new in Apache Iceberg v3 and beyond (OPN201)
この動画では、Amazon Web ServicesのRon OrtloffとYuri ZarubinがApache Iceberg V3の新機能とV4の展望について解説しています。V3の主要機能として、半構造化データを効率的に扱うvariantデータ型、書き込み最適化を実現するdeletion vectors、レコードレベルの変更追跡を可能にするrow lineageを詳しく説明しています。variantではシュレッディング技術により統計情報と述語プッシュダウンが可能になり、文字列パースと比較して最大10倍のパフォーマンス向上が見込めます。deletion vectorsはV2のpositional deletesを改善し、ビットマップをPuffinファイルで永続化することで効率化を実現しています。さらにdefault values、テーブル暗号化キー、ナノ秒タイムスタンプ、geographyとgeometryデータ型などの追加機能も紹介され、V4では改善されたカラム統計、adaptive metadata tree、相対パスなどの提案が進行中であることが説明されています。
※ こちらは既存の講演の内容を最大限維持しつつ自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますのでご留意下さい。
本編
Apache Iceberg V3セッションの概要とプロジェクトの歴史
本日のセッションは Apache Iceberg V3 とその先の新機能についてです。私は Ron Ortloff で、Amazon Web Services のプリンシパルプロダクトマネージャー・テクニカルを務めています。本日は AWS のプリンシパルソフトウェアエンジニアである Yuri Zarubin と一緒にお話しします。ちょっと補足ですが、このセッションはオープンソーストラックのセッションなので、オープンソースと Apache Iceberg 仕様の新機能に焦点を当てています。他にも Iceberg に関連したセッションがたくさんあって、特に削除ベクトルなどの V3 機能を活用する AWS サービスについてのセッションもあります。削除ベクトルを使用する AWS サービスについての素晴らしいセッションなど、他にもたくさんあります。そのあたりについて、ちょっと補足させていただきました。
本日は何についてお話しするのかというと、 本当に Apache Iceberg V3 と、なぜそれに注目すべきなのかについてです。私たちのお客様が最も話題にしている 3 つのトップ機能についてカバーします。それは variant データ型、削除ベクトル、そして行系統です。これらは本当に関心の高い機能として上位に浮上してきていて、お客様のユースケースとの整合性が最も見られている領域です。V3 についての話を締めくくるために、追加機能についても触れます。V3 仕様には素晴らしい追加機能がいくつかあります。それらについて少しお話しして、その後 Yuri が登場して、Apache Iceberg V4 についてもう少し先を見据えた話をします。コミュニティが向かっている方向について、提案が形成され始めていて、それらの提案の周りに勢いが出始めています。Apache Iceberg V4 に向けて物事が形作られ始めています。その後、行動喚起、リソース、そしてあなたは次のセッションに向かうことになります。
V3 に入る前に、 Apache Iceberg というプロジェクトとそのプロジェクト履歴について少しお話ししたいと思います。すべては 2017 年に Netflix で始まりました。Dan Weeks、Ryan Blue、Jason Reed は Netflix で持っていたビッグデータソリューションの周りに多くの共通パターンに気づきました。彼らは Iceberg と呼ぶプロジェクトを開始しました。2018 年に、彼らはそれを Apache Software Foundation に移す過程を開始しました。つまり 2018 年に Iceberg は incubator プロジェクトになりました。これは Apache Software Foundation への最初のステップです。2020 年に、それはトップレベルプロジェクトになりました。これは正式なガバナンスを得て、Apache Software Foundation のプロセスに従うところです。2021 年に、仕様のバージョン 2 がリリースされました。その時点で、大きなリリースと機能は merge on read の機能、行レベルの削除を行う機能でした。これは本当に削除ベクトルの前身のようなもので、これが本日 V3 について話す内容です。2025 年、今年の 5 月に、仕様のバージョン 3 が批准されました。そして私が述べたように、V4 の開発中の提案の周りで物事がどこに向かっているのかについて、形成が始まっているのを見始めています。
その基盤が確立されたので、Apache Software Foundation プロジェクトに関しては、バージョンと新機能について話すときに、Apache Software Foundation 内でどのように物事が機能するのかを理解することが重要な用語がいくつかあります。仕様があります。これは基本的にはドキュメントです。これは Iceberg で作業する誰もが、仕様に準拠するために従う必要があるコントラクトです。これは特に Iceberg の領域で重要です。相互運用性は本当に Iceberg が非常に人気を得た理由の黄金のチケットです。複数のベンダーが実装していて、仕様に準拠していることを確認したいので、データの単一コピーを持つことができ、そのデータの上に多くの異なるコンピュートエンジンを使用できます。仕様はまさにそのコントラクトです。正式に批准される前に、PMC、プロジェクト管理委員会によって投票される必要があります。ただし、Apache プロジェクトに参加したい誰もが、投票に参加し、声を聞かせ、本当にサポートしたいものを支持し、または何かについてフィードバックを提供することを歓迎されていることに留意してください。誰もが参加することを歓迎されています。PMC メンバーの投票だけが公式にカウントされます。
リリース側では、これはスペックが実際に機能し始めるところです。仕様機能があり、参照実装または SDK を通じてリリースで実装されていますが、リリースは正式な Apache Software Foundation ソフトウェアリリースプロセスを通じて行われます。これらは仕様と同じように PMC によって投票されます。
では、なぜこれが重要なのかというと、多くの人が5月に Iceberg V3 spec がリリースされたというマーケティングの話題や噂を聞いて、自分たちの機能はどこにあるのかと疑問に思ったわけです。なぜ Iceberg V3 spec で誰かが話しているのを聞いた機能 X、Y、Z を使えないのかということですね。1.7 リリースから 1.10 リリースまで、ここが community が spec で批准された機能を実装し始めているところなんです。これは今後も続いていくと思いますが、spec で何かが批准されてから、それが実際に市場に出て、あなたが手に取って使える reference implementation になるまでには、タイムラグがあるということを覚えておいてください。
このスライドのポイントは、物事がどこにあるのかについての基礎を提供することです。V3 spec はまだどのリリースでも 100 パーセント実装されていません。これがこのスライド全体の本当の重要なポイントです。 では、これはさておき、V3 に飛び込んで、いくつかの機能について話し始めましょう。最初に話すのは variant data type です。 ちなみに、ちょっと手を挙げてもらいたいんですが、今日 Iceberg を使っている人は何人いますか? これは前にやるつもりだったんですが、わかりました。V3 テーブルを作成した人はいますか?勇敢な人が一人います。この人に賞をあげないといけませんね。素晴らしい。よくやった。では、ここに来て、残りのトークに参加してください。
Variant データ型:半構造化データの柔軟な処理を実現する新機能
variant data type に飛び込む前に、簡単な背景を説明しましょう。Iceberg には本当にいくつかの異なる種類のデータ型があります。primitive types があります。これはさらに細分化できない atomic data types です。string を考えてみてください。これらがあなたの基本的な atomic primitive types です。 また structured types もあります。複数の primitive types を組み合わせることができます。list、map、array などを考えてみてください。ここで重要なのは、固定スキーマを持っているということです。 ここが variant が登場するところで、semi-structured data をサポートする能力があります。ここでは、変動するスキーマを処理する柔軟性が得られます。variant の semi-structured な性質に固定されたコンポーネントはありません。多くの人が variant data type を活用して、受け取った JSON データを処理しているのを見ています。
V3 の variant spec のコンポーネントという観点では、3 つの異なるコンポーネントがあります。file pruning のようなものをサポートするために使用される metadata コンポーネントがあります。 variant データセットから値を取り出して、それらにデータ型を付与する encoding があります。 そして最後のコンポーネントは shredding です。Shredding は基本的に variant data type と variant データセットから要素を取り出して、それらを hidden columns として具体化することです。shredding についてはもう少し後で詳しく話します。
variant data type のユースケースに入る前に、今日 Iceberg V2 を使っている皆さんの中には、semi-structured data を処理しようとするときに経験しているかもしれない痛みについて話しましょう。 最初に多くのお客様がやっているのを見たのは、基本的に semi-structured data を structured data のように見せようとしているということです。彼らはそれを変換を通じてやっています。自分たちのデータに合わせるために、できるだけ近い structure type を選んでいます。これにより、固定スキーマで操作する必要があります。パフォーマンスも少し低下します。これについては後でもっと詳しく話しますが、このような方法で操作しようとしている人もいます。そして、そのデータの変換に関連する追加コストも支払っています。
2番目のパターンは、人々が追加の列を具体化させるというものです。データセットを取得して、自分たちにとって重要な要素をいくつか見つけ出し、その後変換を実行して、それらをテーブル内の別々の列に出力するわけです。
ですから、ここでも変換コストと計算コストを支払うことになりますが、このモデルではかなり良いパフォーマンスが得られます。これらはテーブル内の正当な列で、半構造化されたセットから変換して抽出したものです。統計情報が付与されることになりますし、かなり良いパフォーマンスを発揮します。
そして最後のものがString です。これを私は「諦めモデル」と呼んでいます。半構造化データセットがあるけれど、それを struct に収めることができない。列を具体化させたくもない。では、それを単に string フィールドに放り込んでしまおう、ということですね。そして string パースを行い、parse JSON を実行して、必要に応じてそこからデータを取り出すわけです。このアプローチではそのような柔軟なスキーマが得られますが、ここでパフォーマンスが2回リストアップされているのは、このアプローチのペナルティがかなり大きくなる可能性があるからです。本当に大きくなる可能性があるんです。
ですから、これが今日お客様が行っていることです。ユースケースという観点では、variant を使って本当にお客様が取り組んでいるものは、まず最初にお話しするのは IoT ワークロードです。ここでは、異なるイベント詳細を持つイベンティングタイプのモデルがあり、それは複数の異なる IoT デバイスから取得する可能性があります。スキーマは読み取り時に適用するのが本当に最適で、そのデータを事前に固定スキーマに収める方法を見つけようとするのではありません。また IoT ワークロードでは、異なるタイプの様々なものを取得しているため、半構造化データセット内にフィールドを追加する傾向がより頻繁にあります。ですから、これは variant が半構造化という性質を持つことで、その半構造化タイプのデータを単に吸収でき、それに対してレポートを作成する能力を与えてくれるケースなのです。
次のものはデータパイプラインです。ここでは、これはより多くのデータを variant データ型に着地させることについてで、スキーマに適合させるための変換ロジックを実行する代わりに、基本的にはスキーマを適用するためのロジックをデータパイプラインに組み込んでいるわけです。複数の異なるサプライヤーからデータを取得している顧客がいます。彼らはデータプロバイダーにスキーマを強制するために操作をスケールアップすることができませんでした。ですから基本的には、データセットがスキーマに適合していれば、素晴らしい。それは彼らが持っていたメインパイプラインに入ります。スペック準拠またはスキーマ準拠のデータを提供してくれないサプライヤーがいる場合、彼らは「imparsable fields column」と呼ぶものを作成しました。それは variant でした。彼らはそのデータを単に variant フィールドに放り込み、パイプラインロジックを使用してその variant フィールドから要素を抽出するわけです。それにより、彼らはデータをレポーティングと分析のためにソリューション内の異なるフェーズを通じて移動させる際に、物事を一貫性のあるものに保つことができました。
最後の1つはリアルタイム分析です。ここでも、データが到着する際にそれをクエリできるようにしたいですよね。データの前処理を避けたいわけです。これは、データへのアクセスが必要で、そのデータの上ですぐに分析が必要というモデルです。私たちのあるFinTechの顧客は、株式、債券、暗号資産など、様々な相場分析を大量に行っていました。これらの相場はすべて異なる形式で到着します。このソリューションが事前に前処理や変換を行う時間はありません。彼らはそれをvariant フィールドに投げ込んで、私より賢い人たちや定量分析の専門家にそのデータに対して素早くクエリを実行させたいのです。
ですから、これがvariantのユースケースのようなものです。variantの利点をまとめると、パフォーマンスとコストが本当に大きなポイントです。variantでは、データがカラムナストレージに格納されるので、統計情報が得られ、述語プッシュダウンを行う能力が得られます。異なるユースケースと柔軟なスキーマについて何度も話してきて、このスライドまで構築してきました。これで、動的なスキーマで操作できるようになります。新しい夜間シナリオと詳細が入ってきても、ほぼ自動的なスキーマ進化が得られますよね。新しい要素を含むものを受け取ることができ、正式なスキーマ進化を経ることなく、その上で操作を続けることができます。
効率的なストレージというのも利点で、シュレッディングを行い隠し列を構築する際に圧縮が得られます。圧縮はすぐに箱から出した状態で得られます。そして最後の利点はデータのクエリに関するものです。いくつかのエンジンではドット記法を使ったスキーマナビゲーションが得られます。
エンジンによっては構文が少し異なりますが、variant データ型の階層を下に移動するのは、複数の文字列解析関数をラップするのと比べて非常に簡単です。シュレッディングについて何度か話してきましたが、これが私のデッキ全体で一番好きなスライドなので、覚悟してください。ここに、イベント日付、タイムスタンプ、ソースIDを整数として、そしてイベント詳細をvariant フィールドとして定義したテーブルがあります。3つの列で、かなりシンプルです。ソースシステムからこのタイプのデータファイルを取得します。これをテーブルにロードしたいとします。この場合、V3で何が起こるかというと、プリミティブ型は簡単にマップされ、エンジンを通してテーブルに格納されます。このvariant フィールドでは、Iceberg V3エンジンに持たせるロジックを通してそれを実際にシュレッディングします。ここが私のvariant シュレッダーです。データはシュレッダーを通って流れ、サブ列に分割されます。これがvariant シュレッディングプロセスのエンジン実装です。これらの要素はその後、テーブル内のサブ列、隠し仮想サブ列に格納されます。SKUが整数、アカウントIDが整数、価格が10進数という、これらの隠し列にはデータ型があります。その列をイベント詳細として参照し続けますが、variantの実装の裏側では、クエリできるこれらの隠し列があります。そのクエリはこのようなものになります。このプレディケート列で、実際にそのデータに対してプルーニングを行い、そのプレディケートに一致する値だけを返すことができます。
variant以外のモデルは、特に文字列解析などを行っている場合、フルテーブルスキャンを行う可能性が高くなります。確実にフルテーブルスキャンを行うことになり、それを考えると大変です。しかし、ジョインを行うことを考えてみてください。統計情報のない別のテーブルのアカウントIDでジョインしたい場合、その話がどう終わるか、あなたは知っていると思います。ジョイン条件の不一致、複数のテーブルのスキャン、パフォーマンスが非常に悪くなる可能性があります。相対的なクエリパフォーマンスの差について大まかな感覚を与えるために、variantを1Xのベースラインとすると、構造化型ではパフォーマンスが最大4倍低下する可能性があります。文字列では10倍悪くなる可能性があり、正直なところ、その10倍という数字は、非常にタイトなプレディケートルックアップへのテーブルスキャンを行うベンチマークを作成することができ、10倍よりもはるかに高くなる可能性があります。ですから、セミ構造化型データソリューションの可能性についてvariantを見始めると、これは私たちが議論した代替案の上で見始める可能性があるパフォーマンスプロファイルのタイプです。
Deletion vectors:書き込み増幅を解決する最適化機能
では、variant についてはもう皆さん専門家ですね。次に進んで、deletion vectors についてもう少し詳しく説明しましょう。 Deletion vectors は書き込み最適化機能であり、ストレージ最適化機能で、V2 版の仕様以来、強化されてきた機能です。 Iceberg の中での書き込みモードはどのように機能するのでしょうか?Iceberg の初期段階からある copy on write というデフォルトオプションがあります。 このモデルでは、データファイルがあって、それに対して delete クエリを実行すると、削除されたものが取り除かれた新しいデータファイルを書き直します。こんな感じで説明できます。テーブルに 10 個のレコードがあって、そのうち 1 つを削除したい場合、9 個のレコードが入った新しいデータファイルを書き直すことになります。これが copy on write です。これは大したことではないように見えるかもしれませんが、これを数千のデータファイルにわたって実行すると、書き込み増幅は非常に大きくなります。
膨大な量のデータを書き直すことになります。 一方、merge on read では、同じモデルでデータファイルと delete クエリがあるとき、1 つのレコード、つまり 1 つの positional delete または実装した行レベル削除のタイプに応じた 1 つの delete 条件を持つ delete ファイルを書き込むだけです。書き込み増幅の問題は解決されます。merge on read では、より高速な書き込みが可能になり、消費するストレージも少なくなります。 ただし、読み取りでコストを支払うことになります。今度は、delete ファイルをフルデータファイルと結合して、返すフィルタリングされた結果セットが何かを把握する必要があります。copy on write では、9 個のレコードが入った新しいファイルがあるので、そのセット全体をスキャンするだけで、他のものと組み合わせることについて心配する必要はありません。
これが copy on write と merge on read の違いです。Iceberg にある delete タイプについて話すと、まず V2 では equality deletes 機能を導入しました。これは delete ファイルに条件を書き込むもので、例えば user ID equals ABC のすべてを削除するといった感じで、その delete 条件は読み取り時に使用されてレコードをフィルタリングします。これは Flink のようなストリーミングワークロードで非常に人気があります。 Flink で equality delete ソリューションが多く使用されているのを見かけます。その後、V2 で導入されたもう 1 つの部分が positional deletes です。delete ファイルに delete ポジションを書き込んで、その delete ファイルを読み取り時に使用し、ビットマップに変換して結果セットをフィルタリングします。
Equality deletes は V2 にあり、V3 仕様でも引き続き存在します。Positional deletes は V2 にありましたが、V3 には含まれていません。これらは廃止され、V3 仕様の deletion vector 機能に置き換わりました。 Positional delete ファイルを書き込む代わりに、deletion vectors はビットマップの値を更新してから、そのビットマップを Puffin ファイルの形式でディスクに永続化します。ここに少し微妙な点があります。相変わらず positional deletes ですが、deletion vectors でははるかに最適化されたフォーマットになっています。
Deletion vectors のユースケースと、なぜこのような機能を実装したいのかについて話しましょう。書き込み増幅の部分について話しましたが、deletion vectors が活躍する他の高レベルなシナリオもあります。 GDPR コンプライアンスはその 1 つです。GDPR コンプライアンスで書き込み増幅の問題に直面する人が多いのを見かけます。個人に関する情報を削除する場合、他のビジネス目的でデータがどのように完全に消費されるかとは異なることが多く、そこで書き込み増幅が非常に高いランダム書き込みシナリオに陥ることになります。GDPR 削除を実行する必要がある場合、deletion vectors は確実に検討すべき機能です。
もう一つのユースケースはデータクリーンアップです。 medallion スタイルのアーキテクチャを使っている人たちを見かけます。bronze、silver、gold のレイヤーがあって、bronze はより生のステージングエリアのようなものです。大量のデータをランディングすることになりますし、そのデータの周りにはノイズがたくさんあるかもしれません。そして bronze レイヤーで大量のデータクリーンアップを行いたいことになります。ここが deletion vectors が活躍できる場面で、データクリーンアップ操作の書き込み速度を向上させるのに役立ちます。そして最後のものはインクリメンタルデータパイプラインです。 データパイプラインで merge ステートメントを実行している場合、再度ランダム書き込みタイプの操作をする可能性があります。ここが deletion vectors が merge 操作と非常にうまく機能する場面です。
deletion vectors 内の動作部分がどのように機能するかを理解するために、この例ではディスク上に作成されたいくつかのスナップショットを持つテーブルがあります。snapshot one と snapshot two があります。 別の delete クエリを実行したい場合、生成するデータファイルがあります。そしてビットマップを更新することになります。 その S3 トランザクションの一部として、データファイルがディスクにコミットされることを確認し、ビットマップもディスクにコミットされることを確認します。
そしてそのトランザクションはテーブルにコミットされます。 そのデータを消費する時が来たら、データファイルとビットマップを取得します。 そしてそのビットマップを使用して、呼び出し元のアプリケーションにデータを返す際に結果セットをフィルタリングします。
deletion vectors についてまとめるために、V2 positional deletes と比較して、これがなぜこんなに素晴らしい改善なのかを理解していただきたいと思います。positional delete ファイルでは、delete ファイルが増殖する傾向がありました。delete ファイルを生成することについての仕様やガイダンスがなかったため、多くのお客様が V2 で positional deletes を使用して、小さなトランザクション、小さな delete、小さな update、小さな merge ステートメントからのこれらの delete ファイルが大量にあるという状況になってしまいました。これはあなたに追加の compaction の負担をかけます。なぜなら、そのデータをクリーンアップして、基になるデータファイルを修正する必要があるからです。これは確かに V2 と positional deletes で見ている課題の一つです。
もう一つの課題は、positional delete ファイルがビットマップから Parquet ファイルに変換され、読み取り時にそれが逆になることです。Parquet ファイルからデータを取得して、結果をフィルタリングするためにビットマップをその場で構築しています。 V3 では、これらの課題の多くが解決されています。仕様に従うと、スナップショットごとに 1 つの delete ファイルのみを生成することが許可されています。これにより、これらすべての小さな tiny delete ファイルの問題が排除されます。 ビットマップ自体は Puffin ファイルに直接保存されるため、ビットマップと Puffin ファイルの周りで発生する分解と再構築のプロセスはありません。ライター自体が書き込み操作が発生している間、そのビットマップを維持するため、完全に効率的なビットマップが構築され、維持されています。
Row lineage:レコードレベルの変更追跡を自動化する機能
これが deletion vectors ですね。では row lineage についてちょっと話しましょう。Row lineage は V3 spec に導入された素晴らしい change tracking 機能です。Spec 内の row lineage のコンポーネントには writer specification が含まれています。Iceberg V3 の compliant writer になるには、record レベルの change information を生成する必要があります。Writer として、Iceberg V3 metadata を使用して、snapshot にコミットされた sequence number と row ID を理解することができますが、Writer 側には、row lineage を consume できるようにするために、これらの changed record を生成する責任があります。
Reader 側では、V3 テーブルに新しい hidden column が追加されており、row lineage information を自動的に取得できます。すべての V3 record に row ID と sequence number が付与されます。運用の観点からすると、row lineage は必須機能なので、デフォルトで有効になっており、それをオフにするノブはありません。その情報はあなたが consume するためにそこにあるだけです。Row lineage について私が好きなのは、state information がデータと同期しなくなる split brain scenario に対処したことがある人にとって、これは素晴らしい副次的な利点だということです。Row lineage information は record に直接保存されるので、その row lineage state information は snapshot、record、そしてテーブル自体に存在します。
Time travel をしたい場合、クエリを実行した時点での row lineage がどのようなものであったかの time travel 相当のものを取得することになります。Row lineage のユースケースという観点では、incremental processing は row lineage にとって本当に良い sweet spot です。V3 テーブルから data pipeline への入力として読み出したい場合、sequence number、row ID、および row 上の情報を活用して、パイプラインにフィードするソースとして何が変わったかを理解することができます。Event lifecycle tracking も別の良い例です。Record への変更を時系列で捉えることを考えてみてください。
Orders テーブルを考えると、order は一連の変更を経ます。Submit されて、Billing されて、Process されて、Fulfill されて、Ship されて、Deliver されます。その lifecycle または state change がどのようなものであったかを理解したいのです。Row lineage を使用すれば、それらの変更のそれぞれが、その order に対して同じ row ID 上にあります。Sequence number が毎回インクリメントされるのが見え、その lifecycle がどのようなものであったかを素早く簡単に組み立てることができます。
Slowly changing dimension、または type 2 dimension も同様のモデルを使用します。Row lineage information をフィードして、それらのタイプのものを構築するのに役立てることができます。Debugging も別のユースケースです。他のアプリケーションほど派手ではないかもしれませんが、変換内で row lineage information を追跡し、データを enrich して、システムで構築したものを保持すれば、その計算がどのようにして生まれたかを遡ることができます。計算を実行した row ID と sequence number を使用して、それらのイベントを遡り、1 足す 1 が 7 になったのかを理解することができます。
最後に、row lineage についてですが、これはコンプライアンスを実現するのに非常に優れたツールです。テーブルへの各修正に対してシーケンス番号がスタンプされるので、例えば誰かが従業員テーブルの給与を10億ドルに更新したような場合でも、その変更の流れを理解して、その手順を遡ることができるようになります。
では、row lineage がどのように機能するかについて、いくつかクリックで説明します。 ここに first name と last name という2つのカラムを持つテーブルがあります。 このテーブルの横に、自動的に付与される row lineage カラムをこのグレーのボックスで示しています。テーブルから select star を実行すると、first name と last name は見えますが、row lineage カラムは自動的には表示されません。ただし、実際にそれらを指定して4つのカラムを select すると、画面に表示されているようなすべての情報が見えるようになります。
初期ロードでは、テーブルに2行を入れて、row ID とシーケンス番号を1に設定しています。 次のトランザクションの時刻 T2 では、Diego を Pablo に更新して、シーケンス番号が2に増加するのが見えます。そして3番目のトランザクションでは、ここで複雑さを少し上げてみます。 新しい行を追加してから Carlos を Chuck に更新する merge ステートメントが実行されます。ここで新しいレコードが追加されて新しい row ID が生成され、その両方のシーケンス番号がシーケンス番号3として入ってくるのが見えます。
これについて話すときに、新しい insert のシーケンス番号が1ではないのはなぜかと質問する人もいます。これは単調増加する番号になりますが、テーブル内の現在のシーケンス番号から始まるようになります。これは実際にこれらの変更を消費し始めたいときに重要になります。 ここの select クエリを見ると、これが incremental pipeline について話していたときのようなソースクエリだった場合、実行する各バッチで最後のシーケンス番号の最大値を追跡することができます。ですから、今度は、シーケンス番号が前回取得したときより大きい場合という条件で検索すると、この例の merge ステートメントから出てきた最後の2つのレコードが取得されるようになります。
row lineage についてまとめると、V2 spec では Spark 実装に changelog の手続きとビュー実装がありました。Changelog は基本的にはスナップショット差分を行うメカニズムです。T1 でスナップショットを取得して、それを T2 のスナップショットと一緒に結合して、2つのスナップショット間の違いを理解するというものです。 これを row lineage と比較対照すると、row lineage は基本的に同じタイプの変更追跡を行っているのですが、V2 の changelog ではスナップショット差分を行うための計算コストを支払う必要があります。V3 の row lineage では、これらの詳細は単にレコードに直接スタンプされるだけです。
追加のコンピュートはありません。ただクエリするだけで、writers が自動的に追跡してくれます。 Change logs にはビューのメンテナンスが必要です。スキーマの進化を行う場合、change logs とビューが正しく保守されていることを確認する必要があります。Row lineage は自動的に行われます。これらのメタデータ列、writers、すべてが自動的に処理され、その情報はゼロコンフリクトで存在します。
時間経過に伴う変更を関連付けることを考えると、異なるスナップショット間での time travel クエリを通じて、change logs でそれを行いたい場合、複数のスナップショットを時間をかけて比較する反復的なアプローチを行う必要があるため、少し複雑になる可能性があります。 Raw lineage の場合、その情報がレコードにスタンプされているため、多くの join を行う代わりに、シンプルなクエリで変更の完全なライフサイクルを簡単に組み立てることができます。
V3のコアインフラストラクチャ機能と追加データ型
V3 についてまとめるために、spec で提供されている他の機能についても説明します。 追加機能という観点では、実は 2 つのカテゴリがあります。V3 spec で提供されたコアインフラストラクチャの変更または機能のセットと、追加のデータ型があります。ここで少し時間をかけて、コアインフラストラクチャの部分について説明します。
V3 spec でコアインフラストラクチャ領域に含まれた最初の機能は default values です。 Default values は、値が指定されていない場合にデータを挿入します。テーブルを作成して、列に対してデフォルト値が何であるかを指定すると、パイプラインを実行したりデータを挿入したりするときに、値が指定されていない場合は、スキーマで設定されているデフォルト値を使用することになります。
Iceberg の実装で興味深い点は、デフォルト値自体がメタデータに保存されるということです。ファイル内に定数値を永続化しているのではなく、実際には読み取り時にメタデータを使用して、指定されなかった値を置き換えています。これは Iceberg メタデータを活用してデフォルト値を結果セットに入力できるという、なかなか巧妙な微妙な点です。 テーブルメタデータに値が永続化されているという事実の周りで、ある程度の一貫性と使いやすさが得られます。私は複数の開発者がデフォルト値の指定方法について創意工夫を凝らしたシステムで働いたことがあります。-1 を使う人もいれば、他の値を使う人もいて、それは混乱を招く可能性があります。ここでは、そのデフォルト値はスキーマの右側に保存されており、デフォルト値を置き換えるためのパイプラインロジックやルールについて心配する必要はありません。
次に、コアインフラストラクチャ領域で説明するのは、テーブル暗号化キーです。 テーブル暗号化キーを使うと、テーブルレベルとメタデータレベルで暗号化キーを指定することができます。暗号化が必要なテーブル全体にわたって、きめ細かい制御が可能になります。その暗号化キーを KMS と統合することもできます。キーローテーションもサポートされているので、キーをローテーションすることができます。これはより高度なセキュリティコンプライアンス要件に対応するための高度な機能で、データに対してより細かい制御を提供し、KMS との統合も可能にしますが、同時に Iceberg データに対してより高いレベルの暗号化を実現します。
コアインフラストラクチャ領域で最後に説明するのは、マルチ引数トランスフォーメーションです。 マルチ引数トランスフォーメーションを使うと、トランスフォーメーション内で複数のフィールドを指定できるようになります。 トランスフォーメーションはパーティショニングに使用することもできますし、ソートに使用することもできます。これにより、1 つのカラムだけを選ぶのが難しいシナリオで、より多くの制御が可能になります。クエリシナリオを支援し、データスキューを回避するために、複数のカラムが必要な場合があります。 マルチ引数トランスフォーメーションの要点は、これはパフォーマンス機能であるということです。パーティショニングとソートのためのトランスフォーメーション内で複数のカラムを指定することで、エンドユーザーのクエリパターンをより効率的に調整できるようになります。
V3 に関して説明する最後のセクションは、追加のデータ型です。
このセクションの最初のものはナノ秒タイムスタンプです。ナノ秒タイムスタンプは Iceberg スペースでかなり前から議論されていて、おそらく Iceberg V3 スペックが登場する 1 年前からです。Parquet データやその他のシステムからナノ秒タイムスタンプを持つ顧客がいて、Iceberg に移行する際にその忠実性と精度を保ちたいと考えています。これはかなり長い間、大きなギャップになっていました。 得られるのは、高頻度および時間的なワークロード向けのナノ秒タイムスタンプサポートで、Iceberg V3 ではマイクロ秒からナノ秒への忠実性の向上が実現されます。タイムゾーンサポートの有無にかかわらず、両方で対応しています。 ワークロードの観点からすると、これは頻繁に到着するデータに対してより正確な測定を行いたいストリーミングワークロードに非常に適しています。
次のものはジオタイプです。 これは実は 1 つのスライドに 2 つのタイプがあります。geography と geometry です。geography データ型で位置情報とマッピングクエリのサポートが得られ、geometry データ型で測定と形状を行う機能が得られます。これらのデータ型は両方とも個別の実装であり、個別のデータ型です。これらは開かれた OGC 標準に従っているので、開かれた標準に従う開かれたフォーマットが得られます。これは素晴らしいことです。 Iceberg V3 内に geography と geodata タイプを持つことは、本当にキラー機能だと言えます。 データに対する地理空間対応と、スキーマ進化、タイムトラベル、相互運用性に関する Iceberg のすべての利点が得られます。これでデータに対して Iceberg のパワーと地理空間のパワーが得られるようになり、本当に素晴らしいと思います。
最後に説明するのは unknown です。 Unknown というのはちょっと謎めいた実装なんですが、いわば null のプレースホルダー値みたいなものです。スキーマの進化に対応する際に、ファイルに型やデータが存在しない場合、今後は保護が得られるようになります。 unknown データ型を使うことで、エンジン全体で既知の null プレースホルダーとして使用できます。時々、null の扱いが Iceberg エンジン全体で必ずしも適切に処理されていないという問題に直面する顧客を見かけます。これはそういったシナリオに対抗するのに役立ちます。実は、Iceberg の実装を壊さないようにするためにデータを書き直すまでに至った極端なケースも見てきました。
Apache Iceberg V4に向けた提案:パフォーマンス重視の改善
では、Yuri に引き継ぎたいと思います。明らかに V3 には多くの機能があり、Ron の素晴らしい詳細な説明の後では、それについて知らない言い訳はないと思います。これからやろうとしていることは、コミュニティが V4 で準備している新しいことについて説明し、その後セッションを締めくくって結論を出すということです。 注意すべき点は、これからお話しすることはすべてまだ批准されていないということです。これらはあくまで提案であり、コミュニティはまだ何をするかについて検討中です。これまでの変更の特徴を表現するなら、非常にパフォーマンス重視で、V3 のように機能がぎっしり詰まっているわけではないということです。
まず改善されたカラム統計から始めましょう。カラム統計に詳しくない方のために説明すると、これは Iceberg メタデータファイルの中に保存されるカラムに関する特別な情報で、クエリエンジンがデータを効果的にスキャンするのに役立ちます。現在の問題の一つは、これらの統計の実装方法が特定のユースケースでは非常に効率的ではないということです。特にカラムが多い場合がそうで、それはクエリエンジンがこれらを読む際に、大きなマップをデシリアライズしなければならず、それがメモリプレッシャーを生じさせるからです。
コミュニティが検討しているのは、これらのための適切な構造を作成することで、エンジンが関心のある特定の統計を効率的に参照できるようにすることです。私のように Iceberg を使っているだけなら、本当に知っておく必要があるのは、特定のユースケースでパフォーマンスが向上するということだけです。
次は adaptive metadata tree です。これは小規模な書き込みと削除のパフォーマンスに動機付けられたもので、Ron が先ほど言及していたものです。小規模な書き込みや削除が多い場合、問題になる可能性があります。なぜなら Iceberg にはレイヤーがあり、カタログレイヤーから始まり、ルートメタデータレイヤーがあり、その後さらに 3 つのレイヤーがあり、manifest list、メタデータ、そして実際のデータファイルがあるからです。ファイルを挿入したり、テーブルに対して何らかの更新や書き込みを行ったりするたびに、これらすべてのレイヤーを通過する必要があり、それは非効率になる可能性があります。
提案は、manifest list と manifest を組み合わせて、ルートノードとリーフノードを持つ単一の構造にするというものです。非常に長い提案で、詳しくは説明しませんが、基本的には最終的に小さな書き込みのユースケースに対して1つのレイヤーをスキップすることになります。繰り返しになりますが、Iceberg を使っているだけであれば、これについて特に考える必要はありません。この提案が通れば、V4 で小さな書き込みのパフォーマンスが向上するということを知っておいてください。
最後は 相対パスです。これは実際のところ非常に便利な機能です。manifest に関する一般的な問題の1つは、Parquet ファイル、つまりデータファイルへの絶対パスが含まれているということです。これが問題になる理由は、テーブルをコピーしたい場合、例えば汎用の S3 上に Iceberg テーブルがあって、別の S3 バケットにコピーしたいとします。別のアカウントかもしれませんし、別のクラウドストレージプロバイダーかもしれません。実際のファイルをコピーした後、メタデータファイルが以前のデータファイルを参照しているため、実際にそれらを読むことができなくなったり、クエリエンジンが機能しなくなったりするという問題に直面することになります。
その解決策は、まあ、名前の通りですね。パスを相対的にすることです。これは特に S3 レプリケーションのようなものを使用している場合に非常に便利な機能になります。データ保護やバックアップなど、Iceberg テーブルを別のバケットにレプリケートしている場合です。相対パスを使えば、manifest list を変更することなく、そのデータをクエリできるようになります。
まとめとコミュニティへの参加呼びかけ
では、まとめに入りましょう。Ron は V3 の主な機能について話しました。それは削除ベクトル、行系統、そしてバリアント型です。 その後、彼はコア機能について話しました。つまり、デフォルト値、マルチ引数変換、そして新しい型です。geo、nano、そして unknown です。私は V4 の提案について説明しました。つまり、改善されたスタッツ、アダプティブメタデータ、そして相対パスです。
皆さんに試してみることをお勧めします。最初に手を挙げて V3 を試したことがあると答えた人は1人だけでした。ですから、その数を増やしたいと思っています。うまくいけば、今週の終わりまでに、戻ってからこれらのいくつかを試してみてください。どのベンダーを使用していても、彼らに V3 のサポートがどの程度あるのかを聞いて、テーブルを V2 から V3 に変換してみてください。
Iceberg についてもっと興味がある場合は、ぜひコミュニティに参加してください。ミートアップに参加したり、メーリングリストや Slack で私たちと一緒に参加したり、開発者であれば貢献することもできます。 そして、本当にありがとうございました。ここでの残りの時間を楽しんでいただければと思います。 ありがとうございました。
※ こちらの記事は Amazon Bedrock を利用し、元動画の情報をできる限り維持しつつ自動で作成しています。






















































































Discussion