プロンプトとコンテキスト
あなたのレイクハウスではSparkとTrinoの両方を使用しており、チームは安全なロールバックが可能な共有論理ビューを求めています。Apache Iceberg View Specに基づき、メタデータの発行、クロスエンジンの表現、同時更新、ロールバック、および互換性検証を設計してください。
Iceberg View Specは、エンジン固有のメタストア形式からビュー定義を切り離します。ビューにはデータが含まれず、その定義は参照されたときに実行されます。ビューのメタデータは、スキーマ、バージョン、SQL表現、およびバージョンログを記録します。この面接では、単なるCREATE VIEW構文だけでなく、クロスエンジンの規約と発行の一貫性がテストされます。
面接官が評価するポイント
面接官は、ビューとテーブルの境界、アトミックなメタデータの置換、不変のバージョン、およびオプティミスティックコミットを重視します。優れた回答では、view-uuid、format-version、current-version-id、versions、およびversion-logを説明し、Spark/Trinoの方言の違い、同時編集、ロールバック、スキーマの進化、キャッシュの更新、および実行権限を適切に処理します。
明確化のための質問
共有と実行のターゲット
どのエンジンがビューを読み取りまたは書き込みする必要があるか、編集は双方向か、SQL方言を変換可能か、そしてリーダーがどのくらいの速さで新しいバージョンを検知する必要があるかを確認します。
バージョンとロールバックのポリシー
保持する履歴の量、ロールバックが現在のポインタのみを変更するものかどうか、承認と監査が必要かどうか、そしてベーステーブルのスキーマ変更後に古いビューが引き続き実行可能であるかどうかを明確にします。
一貫性とセキュリティの境界
メタデータストアとカタログが、アトミックなポインタスワップ、競合検出、権限の分離、およびリージョンごとの可視性をサポートしていることを確認します。共有ビューメタデータは、基盤となるデータへのアクセスを自動的に共有するわけではありません。
30秒の回答
「私ならすべてのビューの変更を新しい自己完結型のメタデータファイルに書き込み、カタログのメタデータロケーションをアトミックに置き換えます。このファイルは、安定したview-uuid、フォーマットバージョン、スキーマ、不変のversions、および現在のポインタの変更を記述するversion-logを保持します。各バージョンにはエンジン方言に紐づくSQL表現が含まれ、SparkとTrinoは意味的等価性チェックの後にのみ発行します。ライターはオプティミスティック同時実行制御を使用し、競合が発生した場合は新しいベースから再計算します。ロールバックはcurrent-version-idを既存のバージョンに向け、権限、キャッシュの更新、ベーススキーマの互換性が監査されます。」
ステップバイステップの解決策
ステップ 1: ビューメタデータモデルを定義する
安定したview-uuidを作成し、format-versionを必須値の1に設定し、ベースロケーション、スキーマ、バージョン、current-version-id、およびversion-logを記録します。プロパティはコメントやメンテナンスタスクの設定に使用し、任意のビジネス状態には使用しません。
ステップ 2: 完全なファイルを置き換えて発行する
すべての更新で完全なメタデータファイルを作成します。カタログのポインタを古いロケーションから新しいロケーションへアトミックにスワップしてコミットします。リーダーはロケーションを更新するまでロード済みのバージョンを引き続き使用するため、中途半端に書き込まれた定義を参照するクエリは存在しません。
ステップ 3: バージョンを不変にし、ロールバックを安全にする
バージョンには、バージョンID、スキーマID、作成タイムスタンプ、サマリー、表現、およびデフォルトの名前空間が含まれます。一度作成されると不変であり、SQLや表現の変更があれば新しいバージョンが作成されます。バージョンログはcurrent-version-idの変更を記録するため、ロールバックは履歴を書き換えるのではなく古いバージョンを指します。
ステップ 4: エンジン間のSQL表現を処理する
バージョンには複数のSQL表現を含めることができますが、1つの方言につき1つのみであり、すべてが同じ基盤となる定義を表現している必要があります。パブリッシャーは、Spark、Trino、その他のエンジンについて、パース、カラム型の比較、および代表的な結果セットの比較を行う必要があります。同等の表現を持たないエンジンは、実行を拒否するか明示的なフォールバックに従う必要があります。
ステップ 5: 同時実行性とキャッシュを処理する
ライターは読み取ったメタデータロケーションに基づいて構築します。アトミックなスワップの失敗は、ベースが変更されたことを意味します。クライアントは、固定のTTLのみに依存するのではなく、カタログポインタまたはメタデータロケーションの変更時に更新します。自動化されたパブリッシャーが互いに上書きし続けないように、競合の再試行回数を制限します。
ステップ 6: スキーマの進化と権限を連携させる
ビュースキーマはそのバージョンの一部です。ベースカラムが削除、名前変更、または型変更された場合は、各ターゲットエンジンで代表的なクエリをコンパイルおよび実行します。ビュー定義、ベーステーブル、およびカタログの権限を個別に監査します。ビューへの読み取りアクセス権が元データへの書き込みアクセス権を付与してはなりません。
ステップ 7: 検証、ロールバック、および監視
発行する前に、クロスエンジンの意味的比較、結果スキーマチェック、権限テスト、およびスナップショットレベルのロールバック訓練を実行します。作成者、エンジンバージョン、方言、コミット競合、更新遅延、実行失敗、およびロールバックの理由を記録します。version.history.num-entriesなどのメンテナンス設定で保持履歴を制限し、メタデータの肥大化を監視します。
模範回答
私ならビューを共有されたバージョン管理された論理オブジェクトとして扱います。作成時に安定したview-uuidとフォーマットバージョン1を生成します。変更のたびに、スキーマ、バージョン、表現、バージョンログを含む完全なメタデータファイルを作成し、カタログのメタデータロケーションをアトミックにスワップします。バージョンは不変であり、ロールバックはcurrent-version-idを既存のバージョンに向けるだけです。SparkとTrinoは、パーサー、カラム型、結果セットのチェックによって意味的等価性が証明された後、方言固有のSQL表現を発行します。ライターはオプティミスティック同時実行制御を使用し、競合後は新しいファイルから再試行します。リリース検証では、ベーススキーマの進化、キャッシュ更新、権限の分離、監査可能性、ロールバック後のエンジン横断実行もカバーします。
よくある間違い
- 間違い: 定義を1つのエンジンのメタストアにのみ保存する。 → なぜ失敗するか: 他のエンジンが確実に読み取ったり変更したりできません。 → 修正方法: 共有Icebergビューメタデータと明示的な方言表現を使用します。
- 間違い: 現在のメタデータファイルをその場で直接編集する。 → なぜ失敗するか: リーダーが部分的な状態を参照する可能性があり、ロールバックの安全な境界が失われます。 → 修正方法: 完全な新しいファイルを書き込み、カタログポインタをアトミックにスワップします。
- 間違い: バージョンログを作成タイムスタンプとして扱う。 → なぜ失敗するか: current-version-idの変更を記録するものであり、ロールバックが含まれる場合があります。 → 修正方法: バージョン作成時刻とポインタの履歴を分離します。
- 間違い: 1つのバージョン内で表現を自由に書き換える。 → なぜ失敗するか: 表現は同じ定義を示す必要があり、バージョンは不変です。 → 修正方法: 新しいバージョンを作成し、方言の意味テストを実行します。
フォローアップ質問と回答
ビューのメタデータが自己完結型であるべき理由は何ですか?
リーダーは単一のロケーションからスキーマ、バージョン、表現をパースでき、追跡不能なサイドテーブルに依存することなく、保持された履歴内でロールバックできます。
2つのエンジンが同時に発行した場合はどうなりますか?
ライターは読み取ったメタデータロケーションを含めます。ベースが変更された場合、アトミックなスワップによって一方のコミットが拒否されます。そのライターは、もう一方のバージョンを通知なしに上書きするのではなく、再読み込み、マージ、およびクロスエンジン検証の再実行を行います。
ロールバックによって履歴は破壊されますか?
いいえ。ロールバックは、current-version-idを以前のバージョンに設定するバージョンログのポインタ変更を追加します。古いバージョンと以前のログエントリは監査可能なまま残ります。
ベーステーブルがカラムを削除した場合はどうなりますか?
新しいビューバージョンを発行する前の互換性ゲートとして扱います。サポートされているすべての方言で代表的なクエリをコンパイルおよび実行します。本番環境で障害が発覚するのを防ぐため、発行をブロックするか、エンジンを非サポートとしてマークします。