Data Engineer Associate — 第 14

誰が何をしたか、いくらかかったか、どこで詰まったかを見る

読了 16確認 12更新 2026-08-09

この章で学ぶこと

  • 監査・リネージ・INFORMATION_SCHEMA を使い分ける
  • DBU 課金とクラウド課金の二本立てを説明する
  • system.billing.usage と list_prices を結合する
  • job_run_timeline で run ごとのコストを按分する
  • 症状からログの層を選んで原因に到達する

この章に出てくる用語

system テーブル
system カタログ配下の読み取り専用 Delta テーブル群です。access / billing / lakeflow / query などのスキーマに分かれ、アカウント管理者が有効化します。多くは 365 日保持されます。
データリネージ
テーブルや列が何から作られたかの依存関係です。Unity Catalog がクエリの実行を解析して自動収集し、Catalog Explorer と system.access.table_lineage から参照できます。
INFORMATION_SCHEMA
カタログごとに自動公開される標準ビュー群です。SCHEMATA や TABLES、TABLE_PRIVILEGES で現在のメタデータを列挙します。明示的な SELECT 権限は要らず、履歴も持ちません。
DBU
Databricks Unit の略で、1 時間あたりの処理能力を表す課金単位です。課金は秒単位で、消費量はノード台数と VM のスペック、単価は STANDARD_JOBS_COMPUTE などの SKU で決まります。
SKU
課金の商品コードです。STANDARD_ALL_PURPOSE_COMPUTE のような文字列で、system.billing.usage の sku_name と list_prices の sku_name を結ぶキーになります。
Query History
SQL の文 1 本ごとの実行記録です。statement_id や total_duration_ms、read_rows を持ち、UI から検索できるほか system.query.history には 365 日分が残ります。
イベントログ
宣言的パイプラインの実行記録です。event_log() テーブル値関数で SQL から読め、level は INFO / WARN / ERROR / METRICS、details は JSON 文字列で返ります。
Variable Explorer
ノートブック右側のパネルで、現在のセッションの変数を名前・型・サイズ・値プレビュー付きで一覧します。Python かつ DBR 12.2 LTS 以上ならセル実行中に更新され、Scala や R は完了後です。

リネージと監査 — system.access.audit / table_lineage / column_lineage と INFORMATION_SCHEMA の使い分け

「この集計テーブルを消したら、どのダッシュボードが壊れますか」「先週この顧客テーブルを参照したのは誰ですか」「このカタログにスキーマはいくつありますか」。三つとも後から確認する問いですが、答えを持つ場所は別々です。取り違えると、監査ログを何時間眺めても依存関係は出てきません。覚え方は一行です。構造は INFORMATION_SCHEMA、依存はリネージ、行為は監査ログです。

情報源答えられる問い粒度無償の保持
`INFORMATION_SCHEMA`いま何が存在するか現在のメタデータ履歴なし
`system.access.table_lineage`どのテーブルからどこへ流れたか読み書きイベント365 日
`system.access.column_lineage`どの列がどの列を作ったか列と列の依存365 日
`system.access.audit`誰がいつどの操作をしたかAPI 呼び出し 1 件365 日

下の三つに共通する土台が system カタログです。Unity Catalog を有効にしたアカウントには system という読み取り専用のカタログが用意され、access、billing、lakeflow、compute、query といったスキーマが並びます。中身はただの Delta テーブルで、SQL で集計できます。有効化はアカウント管理者が行い、他の利用者には `USE CATALOG` と `SELECT` が要ります。

いま何があるかは INFORMATION_SCHEMA

現在の姿を知りたいときは `INFORMATION_SCHEMA` です。各カタログの直下に自動で公開される標準ビュー群で、`SCHEMATA` でスキーマ、`TABLES` でテーブル、`COLUMNS` で列、`TABLE_PRIVILEGES` で権限の一覧が返ります。

SELECT schema_name, schema_owner
FROM mycat.INFORMATION_SCHEMA.SCHEMATA;

これだけは他の system テーブルと違って明示的な `SELECT` 権限が要らず、自分が権限を持つオブジェクトだけが自動で絞り込まれて返ります。カタログ直下のものはそのカタログ内しか見えず、横断したいときは `system.information_schema` を使いますが、`hive_metastore` のオブジェクトは含まれません。

どこから来たかはリネージ

画面なら Catalog Explorer の Lineage タブ、SQL なら二つのリネージテーブルです。列は 20 以上ありますが、意味を問われるのは四つです。`source_table_full_name` だけが埋まっていれば読み取りだけ、`target_table_full_name` だけなら書き込みだけ、両方なら読んで書いた 1 イベントです。`entity_type` は `NOTEBOOK`、`JOB`、`PIPELINE`、`DASHBOARD_V3`、`DBSQL_QUERY` のどれかで、実行主体が分かります。`statement_id` は SQL ウェアハウスから実行された場合にだけ入り、Query History へ辿る外部キーになります。`column_lineage` にはさらに `source_column_name` と `target_column_name` が加わります。

SELECT source_table_full_name, entity_type, created_by, event_time
FROM system.access.table_lineage
WHERE target_table_full_name = 'main.sales.sales_agg'
  AND event_date >= current_date() - INTERVAL 30 DAYS;

リネージは実行されたクエリの解析で作られるため宣言もタグ付けも不要ですが、Unity Catalog を経由しない操作は残りません。`spark.read.load("/mnt/raw/...")` のような DBFS パスの直読みは、列どころかテーブルのリネージも記録されません。列リネージは、値を並べただけの `INSERT` のように上流が存在しないイベントも取得しません。UC 非対応のコンピュートも同様です。system テーブルは 1 年で古い行が消えますが、Catalog Explorer とリネージ API は 2024 年 9 月 1 日以降を無期限に保持します。

誰が触ったかは system.access.audit

監査ログは 1 行が 1 回の API 呼び出しで、`user_identity`、`action_name`、`request_params`、`audit_level` などを持ちます。`audit_level` が `ACCOUNT_LEVEL` の行は特定のワークスペースに属さないため、`workspace_id` が `0` で記録されます。既定ではコマンドの本文は残りません。管理コンソールの Advanced タブで詳細監査ログ (`enableVerboseAuditLogs`) を有効にすると、`notebook` と `jobs` の `runCommand`、`databrickssql` の `commandSubmit` と `commandFinish` が追加され、`request_params` に `commandText` が入ります。

行フィルタや列マスク付きテーブルの監査では、誰が叩いたかを `system.access.audit`、どのテーブルと列が読まれたかを `table_lineage` と `column_lineage` で見て組み合わせます。`_delta_log` の JSON やクラスタ上の `/var/log` は、アクセス主体を記録しておらずノード終了で消えるため証跡になりません。検索クエリ例と長期保管の設計は記事「Databricks Audit Logs」(`/articles/databricks/audit-logs/`) に譲ります。

確認 — 穴あけ 3

0 / 3

空欄を押すと選択肢が出ます。間違えても減点はありません。

system.access.table_lineage が保持するのは直近 日分である。

実行された SQL 本文を監査ログに残すには、ワークスペース設定 を有効にする。

いまカタログにどんなスキーマがあるかを一覧するには を使う。

コストの読み方 — DBU 課金式、クラウド課金との二本立て、system.billing.usage

Databricks を使い始めた組織がまず戸惑うのは、請求書が二通届くことです。Databricks からの請求と、AWS / Azure / Google Cloud からの請求が別々に来ます。不備ではなく設計です。Databricks は計算資源の利用料だけを課金し、VM やストレージやネットワークの料金はクラウド事業者が直接請求します。分かれているので、利用者が自分でクラウド事業者と結んだリザーブドインスタンスや割引契約がそのまま効きます。片方だけを見て安いと判断すると、月末にほぼ倍の金額を見ることになります。

DBU は時間あたりの処理能力の単位

Databricks 側の課金単位が DBU です。1 時間あたりの処理能力を表す単位で、課金の刻みは秒単位です。1 時間走らせたら必ず 1 DBU、という意味ではありません。消費量はノード台数と VM のスペックで決まり、単価はワークロード種別で分かれた SKU ごとに違います。同じ処理でも、対話用の `STANDARD_ALL_PURPOSE_COMPUTE` とジョブ専用の `STANDARD_JOBS_COMPUTE` では単価が違います。つまり請求額は「DBU 消費量 × SKU 単価 × 時間」と「クラウド事業者からの VM・ストレージ・ネットワーク費用」の合算です。固定月額ではなく、開発用クラスタが無料になる仕組みもありません。

使用量と単価は別のテーブルにある

ここが試験でも実務でもつまずく点です。使用量を記録する `system.billing.usage` には金額の列がありません。あるのは `usage_unit` (通常 `DBU`) と `usage_quantity` だけです。金額にするには単価表 `system.billing.list_prices` と結合します。

テーブル1 行の意味覚えておく列保持
`system.billing.usage`使用量レコード 1 件`sku_name` / `usage_quantity` / `usage_date` / `custom_tags` / `usage_metadata` / `record_type`365 日
`system.billing.list_prices`ある期間の SKU 単価 1 件`sku_name` / `currency_code` / `price_start_time` / `price_end_time` / `pricing`無期限

`usage_metadata` は構造体で、`cluster_id`、`job_id`、`job_run_id`、`warehouse_id`、`dlt_pipeline_id`、`node_type` などを持ちます。誰の実行かは `identity_metadata.run_as` です。`pricing` も構造体で、`default` が長期見積り用の定価、`promotional` が期間限定の割引価格、`effective_list` がその時点で実際に適用される実効定価です。ここに載るのは公開定価であり、個別の契約割引は反映されません。

もう一つの落とし穴が `record_type` です。値は `ORIGINAL`、`RETRACTION`、`RESTATEMENT` の 3 種類で、後から訂正が入ると、元の行を打ち消す負の数量の `RETRACTION` 行と、訂正後の `RESTATEMENT` 行が追加されます。したがって全種別をそのまま合計するのが正しい読み方で、`record_type = 'ORIGINAL'` だけに絞ると訂正が反映されず過大に数えます。

実務での確認手順も押さえます。日次の DBU 消費を見たいなら `usage_date` で集計して AI/BI ダッシュボードに載せ、しきい値超過はアラートにします。Serverless を含むすべてのワークロードがこのテーブルに載るのに対し、Spark UI から DBU を読み取る方法はなく、Serverless では計算ノード自体が見えません。クラスタイベント API を定期的に叩く運用も課金用の情報源ではありません。金額に関する問いはまず `system.billing` を見ると決めておくと迷いません。タグ設計とチャージバックの手順は記事「Databricks コストアトリビューション実務」(`/articles/databricks/cost-attribution/`) に譲ります。

確認 — 穴あけ 3

0 / 3

空欄を押すと選択肢が出ます。間違えても減点はありません。

DBU は 1 時間あたりの処理能力を表す単位で、課金は 単位で行われる。

system.billing.usage の使用量を金額に換算するには と結合する。

使用量レコードの record_type は ORIGINAL、RESTATEMENT、 の 3 種類である。

system テーブルで全体を見る — job_run_timeline × billing.usage による DBU 按分

「先月いちばんお金を使ったジョブはどれですか」。よく来る質問ですが、`system.billing.usage` だけでは答えられません。入っているのは SKU と ID だけで、ジョブ名も成否もないからです。実行の側は `system.lakeflow` スキーマにあります。

テーブル1 行の意味
`system.lakeflow.jobs`ジョブ定義 1 世代SCD2
`system.lakeflow.job_tasks`タスク定義 1 世代SCD2
`system.lakeflow.job_run_timeline`run の時間スライス追記のみ
`system.lakeflow.job_task_run_timeline`タスク run の時間スライス追記のみ

run が複数行に割れる仕様を先に知る

`job_run_timeline` は run ごとに 1 行ではありません。1 時間を超える run は複数行に分割されます。注意点が二つ出ます。行数をそのまま実行回数として数えると水増しになること、そして `result_state` と `termination_code` は run の最後の行にだけ入り、途中のスライスは `NULL` になることです。`result_state` の値は `SUCCEEDED`、`FAILED`、`SKIPPED`、`CANCELLED`、`TIMED_OUT`、`ERROR`、`BLOCKED` です。

所要時間の列には但し書きが要ります。`setup_duration_seconds`、`queue_duration_seconds`、`execution_duration_seconds` などの 5 列はレガシー Jobs API で作られた単一タスクジョブでしか埋まりません。現行のマルチタスクジョブでは 0 が並ぶため、遅さの内訳をここで切り分けようとしても数字は出ません。

DBU をジョブ実行へ按分する

結合は 2 段です。まず使用量を `usage_metadata.job_id` と `job_run_id` で run 単位に集計し、次に `job_run_timeline` を `workspace_id` と `job_id` と `run_id` で突き合わせます。金額まで出すなら三段目に `list_prices` を `sku_name` と `price_start_time` / `price_end_time` の期間で結合します。

WITH j AS (
  SELECT workspace_id,
         usage_metadata.job_id     AS job_id,
         usage_metadata.job_run_id AS run_id,
         SUM(usage_quantity)       AS dbus
  FROM system.billing.usage
  WHERE usage_metadata.job_id IS NOT NULL
    AND usage_date >= current_date() - INTERVAL 30 DAYS
  GROUP BY ALL
)
SELECT j.*, MAX(t.result_state) AS result_state
FROM j LEFT JOIN system.lakeflow.job_run_timeline t
  USING (workspace_id, job_id, run_id)
GROUP BY ALL ORDER BY dbus DESC;

効くのはジョブとして実行した分だけです。`usage_metadata.job_id` が埋まるのはジョブコンピュートかサーバーレスの場合に限られ、汎用クラスタで手回ししたノートブックには付きません。チーム別に割るならタグを付けて `custom_tags` で集計します。SQL ウェアハウスは `warehouse_id`、宣言的パイプラインは `dlt_pipeline_id` が軸です。

前提です。system テーブルは Unity Catalog 有効なワークスペースが条件で、有効化はアカウント管理者が行います。ジョブ側に `dbutils.system.enable()` を書く必要はなく、その API は存在しません。計算資源側は `system.compute.clusters` と `system.compute.node_timeline` で見え、後者だけ保持が 90 日です。テーブル一覧と有効化手順は記事「System Tables とは?」(`/articles/databricks/system-tables/`) に譲ります。

確認 — 穴あけ 3

0 / 3

空欄を押すと選択肢が出ます。間違えても減点はありません。

job_run_timeline では を超える run が複数行に分割される。

DBU をジョブ実行へ按分する結合キーは workspace_id と job_id と である。

job_run_timeline の duration 列が値を持つのは、 で作られた単一タスクジョブだけである。

詰まったときにどこを見るか — 組込デバッガと Variable Explorer、event log / driver log / Query History / Spark UI の切り分け表

障害連絡で一番時間を溶かすのは、原因の解析ではなく「どこを開くか」で迷う最初の数分です。Databricks は記録の層がいくつもあり、層を間違えると何も書かれていないログを読み続けることになります。症状から入口を引ける表を 1 枚持っておくと、復旧時間が縮みます。

症状最初に開く場所そこで分かること
セルが実行前に赤くなるノートブックのエラー行ハイライトインデントやコロンなどの構文エラー
変数の中身が想定と違うVariable Explorer と組込デバッガ変数の値・型・DataFrame のスキーマ
クラスタが起動しないコンピュートの Event log → Driver logs終了理由と init script の `stderr`
ジョブのタスクが例外で終了Run 画面のタスク出力スタックトレースと再実行対象
パイプラインの行数が合わないイベントログと Data Quality タブExpectations 違反と除外された行数
SQL が遅い・0 行になるQuery History とクエリプロファイルフェーズ別時間と読み取り行数
特定タスクだけ極端に長いSpark UI の Stages / Tasksシャッフル量・スピル・時間の偏り

ノートブックの中で止める

ロジックの誤りは、ログを読むより止めて見るほうが速いです。ノートブックには対話的なデバッガが組み込まれています。対象は Python セルのみで、サーバーレスコンピュート、標準アクセスモードなら Databricks Runtime 14.3 LTS 以上、専用アクセスモードなら 13.3 LTS 以上が要件です。セル左端のガターをクリックしてブレークポイントを置き、ステップ実行とステップインができます。停止中はデバッグコンソールで Python を実行できますが、15 秒でタイムアウトします。

できないことも整理します。Python ライブラリの内部や他のノートブックへはステップインできません。デバッグコンソールで `display()` は使えず、`df.show()` で代用します。そしてローカル PC の `pdb` に attach する構成は取れません。コードはマネージドクラスタのドライバ上で動くためです。手元の IDE から書くなら Databricks Connect を使い、実行はクラスタ側に残します。

Variable Explorer は右側のパネルで、現在のセッションの変数を名前・型・サイズ・値のプレビュー付きで一覧します。Python かつ DBR 12.2 LTS 以上ならセルの実行中に随時更新され、Scala と R、DBR 11.3 LTS 以下の Python ではセルが終わってから更新されます。表示範囲はアタッチ中のノートブックのセッションに閉じています。

ログの層を切り分ける

ログ付いている対象見方保持
イベントログ宣言的パイプラインUI の Event log タブ / `event_log()`パイプラインに紐付く
ドライバログコンピュート (クラスタ)コンピュート詳細の Driver logsログ配信を設定すれば永続
Query HistorySQL の文 1 本Query History UI / `system.query.history`システムテーブルは 365 日
Spark UISpark のジョブとタスクコンピュート詳細の Spark UIクラスタの生存期間

宣言的パイプラインや Lakeflow Connect のインジェストパイプラインの失敗は、イベントログとドライバログが一次調査です。イベントログは `event_log(TABLE(main.sales.my_mv))` または `event_log(<pipelineId>)` というテーブル値関数で SQL から読めます。返る列は `timestamp`、`message`、`level`、`error`、`details`、`event_type` などです。`level` は `INFO`、`WARN`、`ERROR`、`METRICS` の 4 値で、`details` は JSON 文字列です。この関数を呼べるのは対象のストリーミングテーブルまたはマテリアライズドビューの所有者だけです。

ストリーミングテーブルに行が来ない、件数が合わないという症状の定番は、Expectations による除外です。`event_type = 'flow_progress'` に絞り、`details` の `data_quality` に入る `dropped_records` と、期待値ごとの合否件数を確認します。同じ内容は UI の Data Quality タブにも出ます。`ON VIOLATION DROP ROW` で落ちたのか quarantine で別テーブルへ逃げたのかを、ここで一次切り分けします。

ドライバログには `stdout`、`stderr`、`log4j` の出力が集まります。init script が exit code 0 以外で終わるとクラスタは `INIT_SCRIPT_FAILURE` になるので、Event log タブで終了理由を見てから Driver logs の `stderr` を読みます。クラスタを終了すると辿れなくなるため、残すならログ配信を設定します。配信は 5 分ごと、アーカイブは 1 時間ごとで、宛先には Unity Catalog のボリューム (推奨)、S3、DBFS を選べ、`cluster_id` と同名のサブフォルダに書き出されます。

Query History は SQL の文 1 本ごとの記録です。`statement_id`、`statement_text`、`execution_status` に加え、`total_duration_ms` を `compilation_duration_ms`、`execution_duration_ms`、`result_fetch_duration_ms` に分解した内訳と、`read_rows`、`produced_rows` を持ちます。`compute` 構造体の `type` は `WAREHOUSE` か `SERVERLESS_COMPUTE` で、汎用クラスタのクエリは対象外です。長期の分析はシステムテーブル側 (`system.query.history`、365 日) を使います。第 1 節の `statement_id` がここへの外部キーで、リネージから実行本文まで辿れます。

Spark UI は分散実行の内側を見る画面で、Jobs、Stages、Executors のタブがあります。タスク一覧で最大時間と中央値が桁違いなら偏り、Shuffle Read が突出していれば結合の見直し、Spill が出ていればメモリ不足と読みます。構文エラーのように Spark ジョブが起動する前に失敗した場合、Spark UI には何も残りません。

よく問われる症状別の初手

  • 結果が 0 行になった。まず `WHERE` を外して件数・スキーマ・サンプル行を確認します。ウェアハウスのサイズを上げても行は増えません。
  • `COPY INTO` がフォーマット例外で落ちる。Query History とドライバログで失敗したファイル名と理由を特定します。再実行しても冪等なので結果は変わりません。
  • 取り込みが `403` で失敗する。接続文字列ではなく、接続に紐付くサービスプリンシパルの権限を疑います。
  • 本番のバッチは `try` / `except` で想定例外だけを捕捉し、想定外は失敗させて Run output と通知で追います。監査ログにスタックトレースは残りません。

ここまでが後から確認する道具の見取り図です。クエリ履歴からの性能改善の手順は記事「Databricks SQL のクエリ履歴」(`/articles/databricks/dbsql-query-history/`) に譲ります。

確認 — 穴あけ 3

0 / 3

空欄を押すと選択肢が出ます。間違えても減点はありません。

ノートブックの組込デバッガが対応する言語は のみである。

宣言的パイプラインのイベントログを SQL から読むテーブル値関数は である。

クエリ履歴を長期に分析するときは、無償保持が 日の system.query.history を使う。

この章のまとめ

  1. 構造は INFORMATION_SCHEMA、依存はリネージ、行為は監査ログ
  2. リネージは UC を経由した操作だけを記録し、保持は 365 日
  3. usage に金額列はなく、list_prices と結合して初めて金額になる
  4. job_run_timeline は 1 時間を超える run を複数行に分割する
  5. デバッガは Python のみ、長期のクエリ分析は system.query.history

この端末にだけ保存されます(登録不要)

この章の根拠

最終確認 2026-08-09 / 対応バージョン DEA 2026-05-04 改訂版

コース全体

  1. Databricks とレイクハウスの全体像 — なぜ必要か、何がどこに属し、どの計算資源で動くか
  2. データはどこに、どんな形で保存されるか — テーブルの実体と Delta Lake の内部
  3. 計算資源を作り込み、コードを書く場所を決める — クラスタ設定とノートブック/ローカル IDE
  4. Spark はどう動き、SQL で何をどこまで書けるか
  5. PySpark でデータを加工し、遅いコードを見抜く
  6. 流れ込むデータを受け止める — Structured Streaming と Auto Loader のファイル検出
  7. 取り込み時にスキーマをどう扱うか — Auto Loader のスキーマ進化と COPY INTO
  8. ファイル以外からも取り込む — read_files・Lakeflow Connect・JDBC と API
  9. 生データを使える形に育てる — メダリオン設計と宣言的パイプライン
  10. 処理を1つのジョブに束ねる — タスク種別と依存関係の設計
  11. ジョブを動かし、失敗から立て直す — トリガー・リトライ・パラメータ
  12. 書いたものを安全に本番へ届ける — Git 連携とデプロイの自動化
  13. 誰に何を見せるか — Unity Catalog のアクセス制御とアイデンティティ統制
  14. 誰が何をしたか、いくらかかったか、どこで詰まったかを見る
  15. テーブルを保守して速くする — 運用コマンド・保持期間・レイアウト設計・障害復旧
  16. DEA 直前仕上げ — 方式選定・出題範囲対応表・数値総まとめ・引っかけの型