データ接続と統合Iceberg tablesカタログの動作ブランチ化

注: 以下の翻訳の正確性は検証されていません。AIPを利用して英語版の原文から機械的に翻訳されたものです。

Foundry の Iceberg カタログにおけるブランチ分離

Foundry の Iceberg カタログは標準の Iceberg を拡張し、各ブランチが独自の現在のスキーマ、デフォルトのパーティション仕様、およびデフォルトの並べ替え順序を個別に追跡できるようにしています。これらの操作は、実行対象のブランチに分離され、テーブルの main(master)ブランチやその他のブランチには影響しません。これにより、Iceberg テーブルは Iceberg REST カタログ仕様 ↗ に準拠しながら、ブランチでの作業が完全に分離されるという、Foundry ユーザーがカタログデータセットで慣れ親しんでいる動作と一致します。

このページでは、ブランチ分離の仕組み、デフォルトの Iceberg の動作をどのように拡張するか、および Foundry 内で Iceberg を使用する際にどのように自動適用されるかを説明します。また、外部の Iceberg クライアントを使用する際に、この動作を有効にする方法も説明します。

このページで説明するブランチ分離は、Foundry のビルドシステムを通じてジョブを実行する際に適用されます。外部クライアントから Foundry の Iceberg カタログに書き込む場合、デフォルトでは標準の Iceberg のブランチ動作が適用されます。Foundry のブランチ分離を有効にする方法を含め、詳細は外部クライアントでブランチを使用するを参照してください。

Foundry におけるブランチ分離

Foundry でビルドを実行すると、Foundry は Iceberg テーブルに対してブランチ分離を提供します。つまり、Foundry はスキーマ、パーティション仕様、および並べ替え順序の変更を関連するブランチに自動的に分離し、ブランチに限定されたこれらの変更によって、ほかのブランチが意図せず変更されることを防ぎます。これを設定するためにユーザーが何か操作する必要はありません。これは、Foundry のビルドシステムを使用して Iceberg テーブルに書き込む際のデフォルトの動作です。

Foundry は、ブランチ単位のスキーマ、パーティション仕様、および並べ替え順序を、テーブルの Iceberg メタデータファイル内の追加プロパティとして保存します。例:"foundry.branch.feature-branch.schema-id" : "3"。

標準の Iceberg の動作

標準の Iceberg では、スキーマはすべてのブランチで共有されるテーブルレベルの概念であり、テーブル全体で単一の現在のスキーマが追跡されます。詳細は Apache Iceberg のドキュメント ↗ を参照してください。つまり、どのブランチでテーブルのスキーマを変更しても、main とその他すべてのブランチのスキーマが変更されます。

すべてのブランチで単一のスキーマを共有していると、本番環境にマージする前に、ブランチ上でスキーマの変更を分離して開発または検証することが難しくなります。ブランチ上でスキーマの変更をテストするには、テーブルのグローバルスキーマを変更する必要があります。このような変更は、どのブランチで行われたかに関係なく、main 上のテーブルを利用するすべてのコンシューマーに即座に影響します。

Foundry の動作

Foundry の Iceberg カタログは、ブランチ単位のスキーマ、パーティション仕様、および並べ替え順序を自動的に追跡することで、この問題を解決します。ブランチ(たとえば my-branch)上で実行されるジョブが参照するのは、そのブランチが追跡しているスキーマであり、main 上のスキーマではありません。my-branch 上のそのジョブ内で行われたスキーマの変更は、関連するブランチ(この場合は my-branch)に保存され、main 上の現在のスキーマはまったく変更されません。

次のテーブルは、ブランチ単位で管理されるものと、テーブル単位で管理され、すべてのブランチで共有されるものをまとめたものです。

メタデータFoundry による拡張ブランチ機能デフォルトの Iceberg ブランチ機能
スキーマ履歴テーブル単位テーブル単位
テーブルプロパティテーブル単位テーブル単位
現在のスナップショットブランチ単位ブランチ単位
現在のスキーマブランチ単位テーブル単位
デフォルトのパーティション仕様ブランチ単位テーブル単位
デフォルトの並べ替え順序ブランチ単位テーブル単位

Foundry による拡張ブランチ機能では、現在のスキーマはブランチ単位で管理されますが、スキーマの履歴はテーブル単位で管理されます。つまり、ブランチで新しい列を追加すると、そのスキーマはテーブルの共有スキーマリストに追加されますが、main 上の現在のスキーマとしては設定されません。

ブランチコンテキストが確立される仕組み

Foundry のビルドシステムでブランチ上のジョブが実行されると、Foundry はそのジョブのすべてのカタログ操作にブランチコンテキストを自動的に挿入します。ユーザーが何か設定する必要はありません。パイプラインは、追加のコードなしで、そのブランチを対象に入力を読み取り、出力を書き込みます。

例

以下の例では、最も一般的な2つのシナリオを示します。ブランチ上で新しいテーブルを作成する場合と、ブランチ上で既存のテーブルのスキーマを変更する場合です。

例:ブランチ上で新しいテーブルを作成する

開発ブランチ feature/customer-scores 上で新しいテーブルを作成しているとします。トランスフォームは出力用の Iceberg テーブルを作成し、初期データを書き込みます。

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import pyarrow as pa from transforms.api import transform from transforms.tables import IcebergOutput, TableOutput @transform.using(customer_scores=TableOutput("/<path>/customer_scores")) def compute(customer_scores: IcebergOutput): data = pa.table( { "customer_id": pa.array([1, 2, 3], type=pa.int64()), "score": pa.array([0.91, 0.74, 0.88], type=pa.float64()), } ) customer_scores.write_table(data)

フィーチャーブランチで書き込んだ後の customer_scores テーブルの状態は次のとおりです。

Foundry による拡張ブランチ機能デフォルトの Iceberg ブランチ機能
feature/customer-scores 上のスキーマ新しいスキーマ新しいスキーマ
main 上のスキーマ空新しいスキーマ
feature/customer-scores 上のデータありあり
main 上のデータなしなし

Foundry のブランチ分離を使用する場合: ブランチが初期スキーマとスナップショットを保持します。テーブルは main 上に存在しますが、スキーマは空でデータはありません。

デフォルトの Iceberg ブランチを使用する場合: ブランチのスキーマが main 上にも反映されます。

例:ブランチ上で既存のテーブルのスキーマを変更する

今度は、テーブル customer_scores がすでに本番環境に存在しているとします。パイプラインへの変更を検討してテストしており、ブランチ feature/scoring-v2 上で実行するジョブの一部として、新しい列を追加し、既存の列のデータ型を変更したいとします。その際、下流の本番環境のコンシューマーが main 上で参照する内容には影響を与えないようにします。

Copied!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import pyarrow as pa from transforms.api import transform from transforms.tables import IcebergOutput, TableOutput @transform.using( customer_scores=TableOutput("/<path>/customer_scores") ) def compute(customer_scores: IcebergOutput): data = pa.table( { "customer_id": pa.array(["c1", "c2", "c3"], type=pa.string()), "score": pa.array([0.91, 0.74, 0.88], type=pa.float64()), "score_v2": pa.array([0.95, 0.80, 0.92], type=pa.float64()), } ) customer_scores.write_table(data)

feature/scoring-v2 上でジョブを実行した後のテーブルの状態は次のとおりです。

Foundry による拡張ブランチ機能デフォルトの Iceberg ブランチ機能
feature/scoring-v2 上のスキーマ新しいスキーマ新しいスキーマ
main 上のスキーマ古いスキーマ新しいスキーマ
feature/scoring-v2 上のデータありあり
main 上のデータ変更なし変更なし

Foundry のブランチ分離を使用する場合: 新しい列とデータ型の変更は、そのブランチに分離されます。main は元のスキーマを保持するため、下流のコンシューマーは影響を受けません。

デフォルトの Iceberg ブランチを使用する場合: ブランチと main は単一の現在のスキーマを共有するため、書き込み時のスキーマ検証に失敗するか、main のスキーマを更新する必要が生じ、その変更が下流のコンシューマーに反映されます。

外部クライアントでブランチを使用する

Foundry の Iceberg カタログは、Iceberg REST カタログ仕様 ↗に完全に準拠しています。

外部ツールから Foundry の Iceberg カタログにアクセスする場合、カタログの動作は X-PLTR-Branch ヘッダーが設定されているかどうかによって異なります。外部クライアントでブランチを扱う場合は、Foundry のブランチ動作の一貫性を確保するために、X-PLTR-Branch ヘッダーを設定してください。

X-PLTR-Branch ヘッダーが設定されている場合:

  • すべての読み取りおよび書き込み操作のスコープは、自動的にそのブランチに限定されます。
  • ブランチ修飾子が指定されていない場合(または main が参照されている場合)、デフォルトで X-PLTR-Branch ヘッダーに設定されたブランチが使用されます。リクエストで特定の(main 以外の)ブランチが指定されている場合は、ヘッダーのブランチではなく、そのブランチが使用されます。たとえば、ヘッダーが featurebranch1 に設定されている場合、SELECT * FROM table と SELECT * FROM table.branch_main は featurebranch1 を参照しますが、SELECT * FROM table.branch_featurebranch2 は featurebranch2 を参照します。

X-PLTR-Branch ヘッダーが設定されていない場合、Iceberg のデフォルトの動作が適用されます。

  • スナップショットの読み取りには、参照されたスナップショットに関連付けられたスキーマが使用されます。例:SELECT * FROM table VERSION AS OF <snapshot_id>。
  • ブランチの読み取りには、main のスキーマ(テーブルスコープ)が使用されます。例:SELECT * FROM table.branch_my_branch。
  • 書き込みは main のスキーマ(テーブルスコープ)に照らして検証されます。スキーマに準拠しない書き込みは、ブランチに合わせて調整されるのではなく、失敗します。
  • スキーマの変更は main のテーブルスコープのスキーマに適用され、ブランチ内に分離されません。

外部で X-PLTR-Branch ヘッダーを設定する

PyIceberg クライアントのブランチを設定するには、カタログプロパティにヘッダーを追加します。

Copied!
1 2 3 4 5 6 7 8 9 10 from pyiceberg.catalog import load_rest catalog = load_rest( "foundry", { "uri": "https://your.foundry/iceberg", "token": "eyJwb...", "header.X-PLTR-Branch": "my-branch" }, )

Spark では、カタログの設定プロパティとしてヘッダーを渡します。

Copied!
1 2 3 4 5 6 7 spark = ( SparkSession.builder ... .config("spark.sql.catalog.foundry.header.X-PLTR-Branch", "my-branch") ... .getOrCreate() )

外部クライアントを Foundry のカタログに接続する方法の詳細については、Iceberg クライアントを認証すると例: Local Jupyterを参照してください。

制限事項と考慮事項

ブランチ分離を使用する際は、以下の点に注意してください。

ジョブ内のすべてのテーブルに単一のブランチが適用される

ジョブがブランチ上で実行される場合、そのブランチのコンテキストは、ジョブが読み取りと書き込みを行うすべてのテーブルに一律に適用されます。現在、同じジョブ内で入力テーブルや出力テーブルごとに異なるブランチを設定することはできません。Foundry は、解決されたすべての入力ブランチがジョブのブランチと一致することを検証し、一致しない場合はエラーを発生させます。

ブランチが参照するスキーマとパーティション仕様は保護される

ブランチが特定のスキーマまたはパーティション仕様を追跡している場合、main 上で実行される操作であっても、そのスキーマまたは仕様をテーブルから削除することはできません。これにより、並行して実行されるクリーンアップやメンテナンス操作によって、気付かないうちにブランチが破損することを防ぎます。この保護は、ブランチが削除されると自動的に解除されます。

Iceberg のブランチマージ手続きはブランチ分離を考慮しない

チェリーピックやファストフォワードなど、Iceberg 標準のブランチマージ手続きは、スナップショット参照のみを操作し、Foundry のブランチスコープのスキーマプロパティを認識しません。これらの手続きを使用してブランチを main にマージしても、ブランチのスキーマは引き継がれず、main は既存のスキーマを保持します。ブランチでのスキーマ変更を main に確実に反映するには、コードをマージし、Foundry のビルドシステムを使用して main 上で再ビルドします。

対象外の REST エンドポイント

一部の特権 REST エンドポイントは Foundry のブランチから呼び出すことができません。主なものは以下のとおりです。

  • dropNamespace
  • updateNamespace
  • dropTable
  • renameTable
  • commitTransaction
  • createView
  • dropView
  • renameView

バージョン互換性

ブランチ分離は、transforms-tables ライブラリのバージョン 0.1211.0 以降で利用可能です。