プロンプトと適用範囲
あるイベントレイクが複数のベンダーからWebhookを受信します。コアフィールドは安定的ですが拡張フィールドは頻繁に変更され、一部のイベントには日付、タイムスタンプ、バイナリ値、小数が含まれます。Iceberg v3のストレージモデルを設計し、VariantとJSON文字列およびstructを比較し、移行と受け入れ計画を提示してください。
これは半構造化データモデリングをテストするものであり、すべてのフィールドをVariantに配置する決定を求めるものではありません。Icebergの仕様では、Variantは行やファイルによって構造や型が異なる可能性のある値として定義されており、JSONよりも豊富なプリミティブを備えています。これはv3の機能であるため、フォーマットバージョンとリーダーの互換性も設計の一部となります。
面接官がテストしていること
優れた回答では、安定して頻繁にフィルタリングされるフィールドを最上位カラムに昇格させ、頻度が低く変更の速い拡張フィールドをVariantに保持します。Variantの配列やオブジェクトを固定型のリストやstructと区別し、統計情報、述語のプッシュダウン、プロジェクションコスト、エンジンのサポートについて議論します。
面接官は、データコントラクト、命名規則、型の競合、プライバシー、バックフィル、フォールバックパスにも注目しています。優れた回答は、未加工のペイロードから正規のカラムへのデュアルライトまたはビュー戦略を提供し、古いリーダーがv3を解釈できない場合に何が起こるかを明示します。
明確化のための質問
どのフィールドがキーやフィルターになるか
テナントID、イベントタイプ、イベント時刻、冪等性キーが安定的で頻繁にクエリされるか確認します。これらは、クエリのたびにVariantからパースされるパスではなく、型定義されたカラムであるべきです。
拡張フィールドにはどのようなクエリ保証が必要か
監査の再生用であれば、Variantは元の形状を保持できます。低レイテンシの集計やパーティションプルーニングが必要な場合は、検証済みのパスをカラムやマテリアライズドビューにする必要があります。
すべてのリーダーがv3をサポートしているか
Spark、Flink、Trino、サービスSDK、エクスポートジョブをインベントリ化します。v2リーダーが残っている場合は、JSON互換ビュー、隔離されたv3テーブル、またはアップグレードの延期を定義します。
30秒での回答
「私は、安定して頻繁にフィルタリングされるフィールドを型定義されたカラムとして保持し、変更が速く低頻度の拡張フィールドのみをVariantに配置します。VariantはJSON文字列よりも多くの型を保持しますが、カラムの統計情報やプッシュダウンが自動的に提供されるわけではありません。私はパスレジストリ、品質ルール、マテリアライズドカラムを使用してコストを制御します。v3にアップグレードする前にリーダーを洗い出し、v2ジョブには精度の低下を明示した互換ビューを提供し、スキャンバイト数、レイテンシ、型の競合、バックフィルの成功率を測定します。」
ステップごとのソリューション
ステップ1:正規カラムと拡張フィールドを分離する
テナントID、イベント名、イベント時刻、ソース、冪等性キーを、一貫した型、オプショナル性、フィールドIDを持つ最上位のstructフィールドに配置します。ベンダー固有の低頻度オブジェクトはVariantに配置し、再生や監査のためにソースバージョンと元のイベントIDを保持します。
ステップ2:3つの表現を比較する
固定structは、安定したスキーマ、型付き計算、カラム統計情報に適しています。JSON文字列は幅広い互換性がありますが、クエリごとに再パースされ、日付、小数、バイナリのセマンティクスはパーサーに依存します。Variantは、エンジンサポート、統計情報、ガバナンスとのトレードオフを伴いながらも、変更されるオブジェクトや配列に加え、より豊富なプリミティブを可能にします。
ステップ3:Variantコントラクトを定義する
許可されたパスのレジストリを作成します:パス、期待される型、機密性、所有チーム、初検出バージョン、昇格の対象かどうか。不明な高リスク型を暗黙的に文字列に変換するのではなく、拒否または隔離します。
event_id: string
event_time: timestamptz
payload: variant
payload_registry:
vendor.order.total: decimal(18,2)
vendor.order.shipped_at: timestamptzレジストリはデータ品質を管理します。すべてのVariantパスをテーブルスキーマにハードコードすべきではありません。コアなクエリディメンションになった後にのみ、スキーマ進化またはマテリアライズドカラムを通じてパスを昇格させます。
ステップ4:クエリコストを制御する
大規模スキャンにおいてVariantの無制限なワイルドカード走査を避けます。安定したパスに対してプロジェクションビューやマテリアライズドカラムを構築し、イベントタイプと時刻でパーティショニングし、スキャンバイト数、パースCPU、ヒット率を記録します。昇格させる前に、不明なパスをオフラインでサンプリングおよびプロファイリングします。
ステップ5:バージョンとリーダーを処理する
VariantはIceberg v3で許可されています。リリース前に、各リーダーのフォーマットバージョン、ParquetまたはAvroのマッピング、SDKのサポートを確認します。v2ジョブはVariantをJSONとしてシリアライズする互換ビューを使用できますが、そのビューでは型や精度の低下、および効率的にクエリできなくなったフィールドを文書化する必要があります。
ステップ6:バックフィル、競合、プライバシーを設計する
未加工のペイロードと変換バージョンを保持したまま、Variantから新しい正規カラムをバックフィルします。あるパスが小数から文字列に変更された場合、暗黙的に上書きしてはなりません。パスをバージョン管理し、競合メトリクスを出力し、必要に応じて無効なレコードを隔離します。フィールドレベルのマスキング、削除処理、アクセス監査もVariantに適用します。
ステップ7:受け入れマトリクスを構築する
null、混在した型、ネストの深い配列、タイムゾーン、精度、未知のフィールド、古いリーダー、同時書き込み、リトライをテストします。スキャンバイト数、パースCPU、p95レイテンシ、型競合率、再生の一貫性、v2/v3リーダーの成功率を追跡します。
質の高い模範解答
私はすべてのWebhookをJSON文字列として保存することはありません。テナント、イベントタイプ、時刻、冪等性キーは型定義された最上位カラムになり、頻繁に変更されるベンダーの拡張フィールドは、パス、型、機密性のレジストリの下でVariantに入ります。Variantは文字列よりも日付、タイムスタンプ、小数を適切に保持しますが、すべてのエンジンが述語を効率的にプッシュダウンできると思い込むべきではありません。
Iceberg v3にアップグレードする前に、リーダーを洗い出し、v2ジョブには精度の低下を記録したJSON互換ビューを提供します。クエリ層では価値の高いパスをマテリアライズし、未知のパスをプロファイリングします。型の競合は隔離ストリームに入り、バックフィルはバージョンと未加工のイベントを保持します。スキャンバイト数、p95レイテンシ、競合率、再生の一貫性、クロスエンジンの成功率を測定した後にのみ、設計を受け入れます。
よくある間違い
- 症状 → すべてのフィールドをVariantに配置する → 失敗する理由 → コアフィルターが型付き統計情報を失い、クエリコストが予測不能になる → 修正策 → 安定したフィールドを昇格させ、変更される拡張フィールドのためにVariantを予約する。
- 症状 → VariantをJSON文字列として扱う → 失敗する理由 → 日付、小数、バイナリ値が型のセマンティクスを失う → 修正策 → レジストリの下でプリミティブを保持する。
- 症状 → リーダーのテストなしでv3にアップグレードする → 失敗する理由 → 古いエンジンが読み取りに失敗するか、サイレントに性能低下する可能性がある → 修正策 → バージョンマトリクスと互換ビューを構築する。
- 症状 → 型の競合を無理やり文字列にする → 失敗する理由 → ダウンストリームの集計や制約が破損する → 修正策 → パスをバージョン管理するか、隔離して競合を測定する。
- 症状 → バックフィル中に未加工のペイロードを上書きする → 失敗する理由 → 変換の差異を再生または監査できなくなる → 修正策 → 未加工のイベント、変換バージョン、冪等なジョブを保持する。
フォローアップの質問と回答
フォローアップ1:JSON文字列を保持し、クエリ時にパースしないのはなぜですか?
文字列は互換性を最大化しますが、クエリごとにパースコストが発生し、型の精度はパーサーに依存します。これは監査のみの再生であれば許容される場合があります。集計、フィルター、クロスエンジンの整合性を保つには、型コントラクトをVariantまたは正規カラムに移行することが有利です。
フォローアップ2:あるパスが今日は数値で、明日は文字列になったとします。どうしますか?
レジストリを使用して書き込みを拒否または隔離し、ベンダーバージョンを記録します。両方の型が正当である場合は、パスをバージョン管理するか明示的なunionを定義します。クエリエンジンに推測させてはなりません。
フォローアップ3:古いリーダーがIceberg v2しかサポートしていません。どのように移行しますか?
VariantをJSONとしてシリアライズし、精度の低下を文書化したv2互換のテーブルまたはビューを保持します。新しいリーダーでv3をシャドウリードし、段階的にジョブを切り替えます。すべてのジョブはアップグレードゲートで最小フォーマットバージョンを宣言します。
フォローアップ4:Variantのパスはいつ最上位カラムにすべきですか?
そのパスが安定的で、頻繁にアクセスされ、競合が少なく、プロファイリングによってスキャンまたはパースの削減が示された場合に昇格させます。クリーンアップを検討する前に、検証と再生の期間中は未加工のVariantを保持します。