using-dbt-state について
サーバー連携型の dbt State を利用するためのスキルです。選択された dbt オブジェクトの再利用または再構築を判断し、SQL の意味とデータの鮮度を考慮して、開発、CI、本番環境での不要な作業を抑えます。
主な機能
- 01ノードのスキップ、クローン、ビルドを判断
- 02正規化した SQL の意味を比較
- 03上流データの鮮度を考慮
- 04再利用動作の設定と診断
- 05開発、CI、本番環境に対応
活用シーン
- 01実行間で変更のないモデルを再利用
- 02影響を受けない下流ノードの再構築を回避
- 03ノードが再利用または再構築された理由を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dbt-labs/ dbt-agent-skills --skill using-dbt-stateインストール後、Claude Code で/using-dbt-stateを入力して読み込まれたか確認します。
詳細
dbt State の使用
dbt State は、サーバー側で管理される再利用の仕組みです。dbt の state:modified セレクターや --state によるデファーと混同しないでください。
選択された各ノードをビルドする前に、dbt は dbt State サーバーに問い合わせ、そのオブジェクトをスキップ(ターゲットスキーマから再利用)、クローン(別のスキーマから再利用)、またはビルドする必要があるかを確認します。State-Aware Orchestration の後継機能ですが、本番環境の Fusion だけでなく、dbt Core、開発環境、CI でも動作します。
dbt State は有料の製品ですが、dbt プラットフォーム(旧 dbt Cloud)のサブスクリプションは必要ありません。
よくある誤解
| 誤解 | 実際のところ |
|---|---|
「dbt State は単なる state:modified/--state だ」 | 違います。 state:modified は、ファイルの内容を、ユーザーが管理する manifest(常に最新の状態に保つ必要があります。たとえば dbt parse などを使います)と照合してハッシュ化し、state:modified+(すべての子孫ノード)を再ビルドします。dbt State はサーバー上で状態を自動的に管理するため、比較用の manifest を最新の状態に保つ必要がありません。SQL を構文木に解析してセマンティックハッシュを比較し、上流データの鮮度を考慮したうえで、変更に実際に依存する場合に限り子孫ノードを再ビルドします(+ のサブツリー全体ではありません)。 |
| 「Fusion 専用/本番専用だ」 | 任意のオーケストレーターを使って、開発、CI、本番の各環境で、dbt Core、dbt プラットフォーム、Fusionを横断して利用できます。 |
| 「dbt Core のユーザーは利用できない」 | 利用できます。dbt Core 1.7~1.11 では pip install dbt-state が必要です。dbt Core 1.12/v2.0 と Fusion には組み込み済みです。 |
| 「無料だ/ローカルで動作する」 | dbt State サーバーに接続し、dbt プラットフォームのアカウントまたはスタンドアロンの dbt State アカウント(app.state.dbt.com)による認証が必要です。再利用量は **DATT(1 日あたりのアクティブなターゲットテーブル数)**で計測されます(下記の「料金」を参照)。 |
| 「自分のデータが dbt Labs に送信される」 | 送信されるのは最終更新タイムスタンプとSQL テキストです。SQL はハッシュ化された後に破棄されるため、dbt Labs がハッシュ化後のクエリ内容を読み取ることはできず、生データにアクセスすることもありません。 |
再利用の判断方法
選択された各ノードについて、dbt State は有効な選択肢のうち最もコストの低いものを選びます。
- スキップ — オブジェクトがターゲットスキーマに存在し、セマンティックハッシュに変更がなく、
lag_toleranceを超える新しいデータを持つ親ノードもありません。何も実行しません。 - クローン — 一致するオブジェクト(同じハッシュでデータが新しいもの)が別のスキーマ(たとえば本番環境やチームメイトの開発スキーマ)に存在します。これをクローンし、再利用済みとしてマークします。ウェアハウスがサポートしている場合はゼロコピークローンを使用し、サポートしていない場合は CTAS ステートメントを実行して、変換済みデータを別の場所からコピーします。テスト結果も再利用されるため、テストを再実行していなくても、失敗したテストは引き続き表示されます。
- ビルド — 有効な再利用方法がありません。通常どおりビルドし、選択されていない上流ノードは自動的にデファーします。
ノードが実行対象として選択されているものの、その入力がターゲットスキーマに存在しない場合、dbt State は通常どおりデファーを使用します。manifest.json がある場合はそれを使用し、ない場合は generate_*_name マクロに基づいて正しい FQN を可能な範囲で推測します。デファーによって DATT が消費されることはありません。セルフマネージドユーザーは、profiles.yml の defer_to_target 設定を使用してデファー先のスキーマを指定できます。dbt プラットフォームのユーザーには必要ありません。
鮮度を確認するために、dbt は各入力リレーションのウェアハウスメタデータ(または loaded_at_field/loaded_at_query)を取得します。loaded_at が設定されていないビューの場合は、実テーブルが見つかるまで上流をたどります。
クエリの正規化とモデルが再構築される理由
dbt State は解析済み構文ツリーのハッシュを計算するため、空白、コメント、テーブルエイリアス、dbt lint --fix による整形などの見た目だけの変更は無視します。モデルが再構築されるのは、ロジックまたはデータが変更された場合だけです。
揮発性 SQL(current_timestamp()、getdate()、random()):デフォルトではロジックとして扱われます。ハッシュには関数の実行時の値ではなく、関数の名前が使われるため、実行のたびにモデルが無効化されることはありません(そうでなければ、getdate() に依存する下流の処理は再利用できなくなります)。値が変わったときにモデルを再構築するには、次のいずれかを行います。
evaluate_volatile_sql: trueを設定します(推奨。モデル内のすべての関数が対象になり、ほかの設定と同様に継承できます)。dbt State は関数の値をハッシュに反映します。- または、同等の Jinja(例:
{{ run_started_at }})を使用します。Jinja は解析前にレンダリングされるため、コンパイル済み SQL が実行のたびに変わります。
非決定的な Jinja(例:dbt_utils.get_relations_by_pattern が順序の異なるリレーションを返す場合)では、コンパイル済みハッシュが変わり、ロジックに変更がなくても再構築が発生します。
設定の変更: ハッシュに影響するのは、ビルドに関係する設定(materialized、on_schema_change、severity など)だけです。見た目に関する設定(meta、tags)は無視されます。ポストフックが無視されるフィールド(例:meta をウェアハウスのタグとして適用)に基づいてテーブルを変更する場合は、再利用時にもフックを実行するよう execute_hooks_on_any_reuse: true を設定してください。
設定のクイックリファレンス
dbt_project.yml の models: +state:、schema.yml の config.state、または {{ config(state={...}) }} 内で設定します。
| 設定 | デフォルト | 目的 |
|---|---|---|
lag_tolerance | 45m | ノードが再構築の対象となるまでに許容するデータの古さ。データの鮮度のみが対象です。SQL の変更では常に再構築されます。 |
require_fresh_data_from | any | 再構築をトリガーする際に、直接の親のうち any または all のどちらで新しいデータが必要かを指定します。 |
evaluate_volatile_sql | false | 揮発性関数の名前ではなく、実行時の値をハッシュに含めます。 |
pre_clone | if_missing | 実行前に本番環境を複製してインクリメンタルモデル/スナップショットを事前に準備します(never / if_missing / always)。 |
execute_hooks_on_any_reuse | false | ノードが再利用される場合も、プレフック/ポストフックを実行します。 |
defer_to_target | prod | (セルフマネージドのみ、プロファイル)延期/複製元とするプロファイルターゲットを指定します。 |
metadata_warehouse | プロファイルの warehouse | (Snowflake のみ、プロファイル)メタデータの検索に使用する別のウェアハウスを指定します。 |
サポート対象のウェアハウス:Snowflake、Databricks、BigQuery、Redshift。
課金:日次アクティブターゲットテーブル(DATT)
dbt State の使用量は、「ビルドされたモデル」の数ではなく、**DATT(日次アクティブターゲットテーブル)**で計測されます。
- ターゲットテーブルとは、プロジェクトが管理するデータベースオブジェクト(データベース+スキーマごと)です。シード、スナップショット、モデル(インクリメンタルモデルを含む)、各テストが対象です。データベースに保存されないテスト(
store_failuresがオフの場合)も含まれます。例:idにnot_nullとuniqueを設定したdim_customersは、3 つのターゲットテーブル(モデル 1 つ+テスト 2 つ)となります。 - dbt State が特定の日(UTC)にターゲットテーブルに対して少なくとも 1 回のスキップ、複製、またはテストの再利用を行うと、そのテーブルは DATT になります。同じターゲットテーブルを 1 日のうちに何度再利用しても、DATT は 1 つとして数えられます。フルビルドは再利用に該当しません。
- ビューは、再利用または複製された場合も含め、DATT として課金されることはありません。ビューに関連付けられたテストは通常どおり課金されます。
価格の詳細について尋ねられた場合は、https://www.getdbt.com/product/dbt-state を案内してください。
最適な結果を得るための最適化
- 環境ごとの
lag_tolerance— 開発環境では高め(例:1週間)に設定すると、データが少し古いだけの場合に dbt は何もせずに済みます。クローン作成も低コストですが、何もしないほうがさらに低コストです。例:# dbt_project.yml models: +state: lag_tolerance: "{{ '4h' if target.name == 'prod' else '7d' }}" - 開発では引き続きセレクターを使用してください。 dbt State が再利用する対象テーブルは、その日の DATT としてカウントされます(
lag_toleranceの範囲内にあるものも含みます)。作業対象のノードだけを選択し、残りは通常のデファーに任せてください。未変更で選択されていないノードは、dbt State の使用量に影響しません。 - 本番環境では複雑なセレクターの使用を減らしてください。 dbt State によって、ほとんどのジョブは通常の
dbt buildに近い形になります。ジョブごとに手動で選択を細かく調整するのではなく、何を再構築するかを dbt State に判断させてください。過剰なビルドを防ぐには、lag_toleranceを指定します。 - 再利用される可能性を高めるため、
select *ではなくカラムを指定してください。 dbt State がtable.*などのカラムセットが同じであると証明できない場合、安全のために再構築します。これは特にビューで重要です。この処理では、現在 Fusion の静的解析は使用されません。
動作が分かりにくい場合の診断
| 症状 | 原因/対処 |
|---|---|
current_timestamp() を含むモデルが再構築され続ける | どこかで evaluate_volatile_sql: true が設定されているか、Jinja の値(例:run_started_at)によってコンパイル済み SQL が変わっている可能性があります。再利用したい場合は、デフォルトのままにして揮発性 SQL を評価しないでください(ロジック)。 |
| 「変更がない」のにモデルが再構築される | 表面的な変更が原因ではありません(そのような変更は正規化によって取り除かれます)。順序が未定義のマクロ出力など、非決定的な Jinja、ビルドに関連する設定の変更、または lag_tolerance を超える、より新しい上流データを確認してください。メタデータテーブルでは、新しい行が追加されていなくても、insert コマンドによってテーブルが変更されたと見なされることがあります。loaded_at_field の使用も検討してください。ただし、データウェアハウスでのコストが高くなる可能性があります。メタデータクエリは無料の場合が多い一方、loaded_at_field は通常の有料クエリになります。 |
| 再利用されたモデルで post-hook が実行されなかった | デフォルトでは再利用時にフックは実行されません。execute_hooks_on_any_reuse: true を設定してください。 |
| ノードが再利用/再構築された理由を知りたい | dbt-state explain コマンド(dbt v1.7–1.12)を使って、判断内容を確認してください。 |
| 認証/アクセスが必要 | dbt platform アカウントまたはスタンドアロンの dbt State アカウントでログインしてください。組織の場合は、dbt_project.yml の dbt-cloud: 配下に state-org-id を設定します。 |
v1(Python)と v2(Rust/Fusion)の比較
| dbt Core 1.7–1.11 | dbt Core 1.12 / v2.0 | Fusion | |
|---|---|---|---|
| インストール | pip install dbt-state が必要 | 組み込み | 組み込み |
- dbt v1.7~1.11 のユーザーが dbt State を使用するには、別途
dbt-stateパッケージをインストールする必要があります。 - dbt v1.12 以降のユーザーには、
dbt-stateパッケージが自動的に含まれています。 - dbt v2.0 以降(Core または Fusion のいずれのディストリビューションでも)には、クライアントロジックの Rust 実装が組み込まれているため、別途インストールする必要はありません。
再利用の動作、設定、クエリの正規化はサーバー側で行われ、すべてのエンジンで一貫して動作します。v1 の主な違いは、1.7~1.11 では dbt-state を別途インストールする点です。dbt-state explain による診断は dbt v2 では利用できません。
関連ドキュメント
- 概要:
/docs/deploy/dbt-state-about - セットアップ:
/docs/deploy/dbt-state-setup· 例:/docs/deploy/dbt-state-examples - アクティビティの監視:
/docs/deploy/dbt-state-interface· デファー:/docs/deploy/dbt-state-deferral· CI/CD:/docs/deploy/dbt-state-cicd - 設定:
/reference/resource-configs/dbt-state-configs·lag_tolerance·defer_to_target