第2章 データ取り込みとロード / 想定学習時間:30〜40分 / 最終確認:2026年8月

2-5. JDBC/ODBC・RESTクライアントによる取り込み

🎯 この節の学習目標

1. 自前実装パターンの位置づけ

2-4 で見たとおり、対応するマネージドコネクタやパートナーコネクタがあるならそちらが優先です。しかし現実には、コネクタが対応していないデータベースや社内 API、特殊な抽出条件が必要な場面が残ります。そこで登場するのが、ノートブックに抽出コードを書き、Lakeflow Jobs(旧 Workflows)でスケジュールする自前実装パターンです。

外部ソースリレーショナル DB / REST API
JDBC ドライバ / requests などの HTTP クライアント
ノートブックで抽出認証情報はシークレットから取得
DataFrame 化(必要なら watermark 列で増分抽出)
Delta 形式で書き込みappend / overwrite / MERGE
Lakeflow Jobs で定期実行
UC 管理 Delta テーブル

図:JDBC / REST による自前取り込みパイプラインの構成

2. JDBC による外部データベースの読み取り

Spark には JDBC データソースが組み込まれており、spark.read.format("jdbc") で外部データベースのテーブルを DataFrame として読み取れます。

💡 具体例:外部 RDB のテーブルを読み取り、UC 管理テーブルへ書き込む

# 認証情報は Databricks シークレットから取得(コードに直書きしない)
user     = dbutils.secrets.get(scope="ingest", key="db_user")
password = dbutils.secrets.get(scope="ingest", key="db_password")

df = (spark.read
  .format("jdbc")
  .option("url", "jdbc:postgresql://db.example.internal:5432/sales")
  .option("dbtable", "public.orders")
  .option("user", user)
  .option("password", password)
  .load()
)

# UC 管理 Delta テーブルへ書き込み
df.write.mode("append").saveAsTable("main.bronze.orders")

dbtable にはテーブル名のほか、括弧で囲んだ副問い合わせも指定できます。読み取り時にソース側で絞り込みたい場合は query オプションで SQL を渡す方法もあります。

いったんクラウドストレージに中間ファイルとして書き出してから 2-2・2-3 の仕組みでロードする構成も可能ですが、DataFrame として読めているなら直接 UC 管理テーブルへ書き込むのが最短です。なお ODBC は主に BI ツールなど外部クライアントから Databricks へ接続する文脈で登場する規格で、ノートブックからの読み取りでは JDBC を使うのが通常です。

3. 増分抽出:watermark 列

JDBC 読み取りには COPY INTO や Auto Loader のような「既処理の自動記録」がありません。毎回全件を読むとソース DB に負荷がかかるため、watermark 列(更新日時や連番 ID など、単調に増える列)を使って「前回読んだところから先だけ」を抽出します。

# 前回ロード済みの最大更新日時をターゲットテーブルから取得
last_ts = (spark.table("main.bronze.orders")
           .selectExpr("max(updated_at)").first()[0])

query = f"(SELECT * FROM public.orders WHERE updated_at > '{last_ts}') AS t"

df_inc = (spark.read.format("jdbc")
  .option("url", jdbc_url)
  .option("dbtable", query)
  .option("user", user)
  .option("password", password)
  .load()
)
df_inc.write.mode("append").saveAsTable("main.bronze.orders")

📝 試験のポイント

「JDBC で毎回フルテーブルを読んでいて遅い・ソースに負荷がかかる」という問題文には、「更新日時などの watermark 列で増分抽出する」が対策の軸になります。増分の管理責任が仕組み側にある(COPY INTO / Auto Loader / マネージドコネクタ)か、実装者にある(JDBC / REST)かの対比は、方式選択問題でも効いてきます。

4. REST API クライアントによる取得

社内 API や外部サービスの REST API からの取り込みは、Python の requests などの HTTP クライアントで取得し、DataFrame に変換して Delta へ書き込みます。

💡 具体例:REST API から JSON を取得して Delta テーブルへ

import requests

token = dbutils.secrets.get(scope="ingest", key="api_token")

resp = requests.get(
    "https://api.example.internal/v1/products",
    headers={"Authorization": f"Bearer {token}"},
    timeout=30,
)
resp.raise_for_status()
records = resp.json()["items"]   # 辞書のリスト

df = spark.createDataFrame(records)
df.write.mode("overwrite").saveAsTable("main.bronze.products")

API 応答のページネーション(次ページの繰り返し取得)やレート制限への待機は、抽出コード側で実装します。取得件数が多い場合は、ループでページを集めてから一括で createDataFrame するのが基本形です。

REST 取得のコードはドライバノード上の単一プロセスで動く点に注意してください。Spark の分散処理が効くのは DataFrame 化した後です。巨大なデータを1つの API から吸い出す用途には向かず、その場合はソース側にエクスポート機能(ストレージへのファイル出力)がないかを先に検討します。

5. 運用の3点セット

5-1. 認証情報はシークレットで管理する

パスワードや API トークンをノートブックに直書きするのは厳禁です。Databricks シークレット(dbutils.secrets.get(scope, key))に格納し、コードからは参照だけを行います。シークレットの値はノートブックの出力上では自動的に伏せ字(REDACTED)になります。

5-2. ドライバの制約

主要なデータベースの JDBC ドライバは Databricks Runtime に同梱されていますが、それ以外のデータベースではドライバの JAR をクラスタにライブラリとしてインストールする必要があります。また、サーバーレスなど環境によってはライブラリ導入やネットワーク到達性に制約があるため、接続先への経路(プライベートネットワーク等)も含めて事前確認が必要です。

5-3. Lakeflow Jobs でスケジュールする

抽出ノートブックは手動実行で終わらせず、Lakeflow Jobs のタスクとして登録して定期実行します。リトライ・タイムアウト・失敗時の通知を Jobs 側に設定すれば、自前実装でも運用品質を確保できます(第4章で詳述)。

注意点内容
認証情報シークレットで管理。コード直書き・平文の設定ファイルは不可
ドライバ同梱外の DB はドライバ JAR のインストールが必要。環境の制約に注意
増分抽出watermark 列で差分のみ抽出。自動記録の仕組みはないので実装者の責任
ソース負荷業務 DB への大量読み取りは業務時間を避ける、読み取り専用レプリカを使うなどの配慮
オーケストレーションLakeflow Jobs でスケジュール・リトライ・通知を構成

✅ この節のまとめ

練習問題

問1. ノートブックから JDBC で外部データベースに接続する際の認証情報の扱いとして最も適切なものはどれか。

  1. ノートブックのセルにパスワードを直接記述し、実行後に消す
  2. Databricks シークレットに格納し、dbutils.secrets.get で参照する
  3. クラスタの環境変数に平文で設定し、全ユーザーと共有する
  4. パスワードをテーブルに保存しておき、SELECT で取得する
解答と解説を見る

正解:B

認証情報はシークレットで管理し、コードからは参照のみを行うのが標準です。シークレット値はノートブック出力で自動的に伏せ字になります。Aは実行履歴やバージョン履歴に残るため「後で消す」では守れません。Cは平文かつ共有範囲が広すぎ、Dはテーブルの参照権限を持つ全員に漏えいします。

問2. JDBC で業務データベースの大きなテーブルを毎晩取り込んでいるが、毎回全件を読んでおり、実行時間とソース DB への負荷が問題になっている。最も適切な改善策はどれか。

  1. 更新日時などの watermark 列を使い、前回ロード以降の行だけを抽出するように SQL を変更する
  2. COPY INTO に切り替える(JDBC URL を FROM 句に指定する)
  3. クラスタのノード数を増やして全件読み取りを高速化する
  4. 取り込みをやめて、分析クエリを毎回ソース DB に直接発行する
解答と解説を見る

正解:A

JDBC には既処理の自動記録がないため、増分抽出は watermark 列で自作します。これで転送量とソース負荷の両方が減ります。Bは誤りで、COPY INTO のソースはクラウドストレージ上のファイルであり、JDBC URL は指定できません。Cは読み取り自体の量が減らないためソース DB の負荷問題を解決しません。Dはソース DB への負荷をむしろ恒常化させ、取り込みの目的に反します。

問3. REST API からデータを取得して Delta テーブルに書き込むコードの流れとして正しいものはどれか。

  1. spark.read.format("rest") で API の URL を直接読み込む
  2. requests で API を呼び出して JSON を取得し、spark.createDataFrame で DataFrame 化して saveAsTable で書き込む
  3. COPY INTO の FROM 句に API の URL を指定する
  4. Auto Loader の cloudFiles.format に "rest" を指定する
解答と解説を見る

正解:B

REST 取り込みの基本形は「HTTP クライアントで取得 → DataFrame 化 → Delta 書き込み」です。Spark には REST API を直接読むデータソースは組み込まれていないため、Aのような書き方はできません。CとDも誤りで、COPY INTO と Auto Loader のソースはクラウドストレージ上のファイルであり、HTTP エンドポイントは扱えません。

問4. JDBC / REST による自前取り込みパイプラインの運用として最も適切なものはどれか。

  1. 抽出ノートブックは担当者が毎朝手動で実行する
  2. 抽出ノートブックを Lakeflow Jobs のタスクとして登録し、スケジュール・リトライ・失敗通知を設定する
  3. ノートブックの末尾に無限ループを書き、常時実行し続ける
  4. スケジュール実行はマネージドコネクタ専用の機能なので、自前実装では利用できない
解答と解説を見る

正解:B

自前実装の取り込みは Lakeflow Jobs(旧 Workflows)でオーケストレーションするのが標準です。スケジュールに加えリトライや通知を Jobs 側で構成することで、運用品質を確保できます。Aは属人化と実行漏れのリスクがあります。Cはクラスタを占有し続けるうえ、障害時の再開制御もできない悪手です。Dは誤りで、Jobs は任意のノートブック・スクリプトをスケジュールできます。