代表的な面接トピック

データエンジニアリング面接:統制可能なArrow Flight SQLサービスをどのように設計するか?

データ難しい
Offer.cc 編集チーム公開日 更新日

質問

あなたの会社では、BI、ノートブック、およびバッチクライアントがArrow Flight SQLを介して複数のデータベースにアクセスできるようにしたいと考えています。サーバー側のプロトコルアダプター、クエリライフサイクル、認可、結果ストリーミング、キャンセル、およびテナントガバナンスを設計してください。

プロンプトとコンテキスト

複数のアナリティクスクライアントが異なるSQLエンジンにアクセスする必要があります。既存のJDBC/ODBCパスでは、大きな結果セットに対して行・列の変換やコネクションプールの逼迫が発生するため、チームはカラムナー転送にArrow Flight SQLの採用を検討しています。SQLリクエストからFlightデータストリームに至るまでのサービスを、メタデータ、結果エンドポイント、認証、バックプレッシャー、キャンセル、監査、および分離を含めて設計してください。

面接官がテストしていること

  • Flight RPCおよびArrowメモリフォーマットにおけるFlight SQLの境界を理解しているか。
  • GetFlightInfo、GetSchema、DoGet、DoPut、およびDoActionの違いを把握しているか。
  • クエリハンドル、結果パーティション、フロー制御、キャンセル、およびリトライを設計できるか。
  • SQLの認可、テナントリソース、機微なカラム、および監査を適切に処理できるか。
  • JDBC/ODBCアダプター、機能ネゴシエーション、およびオブザーバビリティを説明できるか。

最初に明確にすべき質問

  1. クライアントの用途は主にインタラクティブクエリ、バッチエクスポート、ストリーミング書き込みのどれですか?
  2. 結果サイズ、同時実行クエリ数、Time-to-first-byte、およびテナントクォータはどの程度ですか?
  3. すべてのバックエンドがArrowをネイティブに実行しますか、それともゲートウェイで結果を変換する必要がありますか?
  4. OAuth、mTLS、行・列ポリシー、またはリージョン間アクセスが必要ですか?
  5. キャンセルによって解放すべきデータベース、メモリ、およびオブジェクトストレージのリソースは何ですか?

30秒での回答

「私ならサービスを認証とテナントポリシー、SQLプランニング、Flight SQLプロトコル適応、および結果ストリームゲートウェイに分割します。クライアントはGetFlightInfoを呼び出してクエリハンドルとエンドポイントを取得し、DoGetを使用してArrowのRecordBatchをプルします。メタデータにはGetSchemaを使用し、書き込みやパラメータ付きアクションにはDoPutまたはActionセマンティクスを使用します。ゲートウェイはスキャン、同時実行数、保持期間を制限し、ダウンストリームのバックプレッシャーを実行エンジンに伝播させ、キャンセルをサポートします。各ハンドルにはID、ポリシー、プランバージョン、および監査データが含まれます。機微なカラムはプランニング中に削除され、エンジンの差異は機能ネゴシエーションを通じて公開されます。」

ステップバイステップの詳細解説

1. プロトコルと実行の境界を分離する

Flight SQLは、SQLメタデータ、クエリ、およびプリペアドステートメント用のProtobufコマンドを定義し、GetFlightInfo、GetSchema、DoGetなどのFlight RPCを再利用します。ゲートウェイがID、ポリシー、ライフサイクル、およびフロー制御を担い、アダプターが論理プランをエンジン固有のSQLとArrowバッチに変換します。

2. クエリライフサイクルを設計する

推測不可能なクエリハンドルを作成する前に、認証を行いテナントの機能を解決します。GetFlightInfoはスキーマ、エンドポイント、および有効期限を返します。DoGetはそれらのエンドポイントからRecordBatchを読み取ります。リトライによって重複実行が発生しないよう、計画中(planned)、実行中(running)、排出中(draining)、キャンセル済み(cancelled)、失敗(failed)、期限切れ(expired)の各状態を追跡します。

json
{
  "queryHandle": "q_7f2a",
  "schemaVersion": 3,
  "endpoints": [{"ticket": "t_01", "location": "grpc://flight-2"}],
  "expiresAt": "2026-08-01T13:00:00Z",
  "cancelToken": "c_7f2a"
}

3. カラムナー結果とバックプレッシャーを処理する

エグゼキューターはターゲットサイズでRecordBatchを生成し、ゲートウェイはDoGetの消費状況に基づいてプリフェッチとメモリウォーターマークを制御します。ゲートウェイで結果全体を実体化させず、低速なクライアントに対しては一時停止やディスクスピルを行います。クロスノードのエンドポイントはパーティションを保持するワーカーを指す場合がありますが、ゲートウェイは引き続きチケット、テナント、および有効期限を検証します。

4. キャンセル、障害、およびリトライを設計する

単一のキャンセルトークンをデータベースのキャンセル、ワーカーストリーム、およびオブジェクトストレージの一時ファイルにマッピングします。切断後、未確認のバッチをリトライできるのはハンドルを持つ冪等な読み取りのみです。書き込みには、推測によるDoPutの再試行ではなく、明示的なトランザクションまたはActionセマンティクスが必要です。失敗時のレスポンスには、SQLや機微なデータを含めず、分類されたステータスとトレースIDのみを公開します。

5. 認可とテナントガバナンスを強制する

認証にはmTLS、OAuth、またはFlight認可ヘッダーを使用し、クレデンシャルはTLS経由でのみ送信します。ユーザー、ロール、およびテナントを、データベースID、許可されたカタログ、スキーマ、テーブル、行フィルター、カラムマスク、およびリソース制限にマッピングします。プランニング中にカラムプルーニングとパラメータバインディングを適用し、管理者の接続にユーザーのSQLを直接連結してはなりません。

6. オブザーバビリティと互換性を構築する

クエリハンドル、テナント、データベース、プランバージョン、バッチ数、バイト数、最初のバッチのレイテンシ、キャンセル理由、およびピークリソースを記録します。メトリクスをテナントおよびエンジンごとにセグメント化し、生データはログから除外します。セマンティクスの違いを文書化しながらJDBC/ODBCドライバーアダプターを提供し、GetSqlInfo、GetCatalogs、および関連するメタデータ呼び出しを通じてサポート状況を公開します。

優れた回答例

「Flight SQLサービスは、SQLセマンティクスとArrowカラムナーストリームを統合します。クライアントはGetFlightInfoからスキーマ、チケット、エンドポイント、および有効期限を取得し、DoGetでRecordBatchをプルします。プランニング中、ゲートウェイはID、テナント、行・列ポリシー、およびリソース予算を適用します。結果はストリーミング状態を維持し、ダウンストリームのバックプレッシャーが実行エンジンに伝播します。低速なクライアントは一時停止またはスピルが可能です。キャンセル時にはデータベース、ワーカー、および一時ファイルを確実に停止・クリーンアップする必要があります。冪等な読み取りハンドルはリトライ可能ですが、書き込みには明示的なトランザクションセマンティクスが必要です。すべてのクエリに監査用IDとトレースIDが付与され、機能ネゴシエーションによってエンジン間およびJDBC/ODBCの差異を吸収します。」

よくある間違い

  • Flight SQLをJSON HTTP APIのように扱う → カラムナーバッチとエンドポイントのセマンティクスが失われる → Flight SQL RPCのライフサイクルを中心に設計する。
  • ゲートウェイで完全な結果をキャッシュする → 大規模クエリでメモリが枯渇する → バッチをストリーミングし、バックプレッシャーを伝播させる。
  • 接続確立時のみ認証を行う → 行、列、テナントのポリシーが欠落する → プランニング段階でポリシーを適用する。
  • 切断後にすべてのクエリを再起動する → データベース負荷と重複書き込みが増加する → 読み取りはハンドルで、書き込みはトランザクションまたはActionセマンティクスでリトライする。
  • 機能を無視する → クライアントはすべてのSQL機能が存在すると想定してしまう → GetSqlInfoなどのメタデータを使用してネゴシエーションを行う。

フォローアップ質問と回答

なぜGetFlightInfoとDoGetを分けるのですか?

GetFlightInfoはスキーマ、チケット、エンドポイント、および実行情報を返し、DoGetはデータストリームを転送します。これにより、結果パーティションを異なるワーカーに分散させることができ、クライアントがエンドポイントを並列または遅延して読み取れるようになります。

低速なテナントクエリをどのように制限しますか?

プランニング中にスキャンバイト数、同時実行数、メモリ、および実時間のクォータを設定し、実行状況をサンプリングして制限を超えた場合にキャンセルまたは処理をデグレードさせます。大規模テナントが共有ワーカーを独占しないよう、テナントおよびエンジンごとにクォータを測定・管理します。

DoPutで重複書き込みをリトライできますか?

はい、可能です。書き込みにはトランザクションID、バッチシーケンス、および冪等性制約が必要であり、明示的なコミットポイントとリトライ結果を伴う必要があります。コミットステータスが不明な場合は、やみくもに再実行するのではなく調整(レコンシリエーション)ステータスを返します。

クライアントがデータベースに直接接続してはならない理由は何ですか?

直接アクセスは、認可、監査、スロットリングの共通化やエンジン間の動作調整を困難にし、データベースのネットワーク境界を外部に晒してしまいます。Flight SQLゲートウェイは、Arrowネイティブの転送効率を維持しながら、これらの制御を一元管理します。

公開情報ソース

関連する質問