dbt operations(dbt run-operation)は、モデル実行とは独立して Jinja マクロを直接呼び出すための仕組みです。権限付与、スキーマ作成・削除、メタデータ更新などの管理系タスクを自動化できます。
本稿では、安定機能である run-operation の基本、ベストプラクティス、よくある実装例、スケジューリング方法をまとめ、Analytics Engineer 試験に必要な観点も補足します。
operations は dbt の DAG 外でマクロを実行します。実行時には target(プロファイル/接続情報)、env_var、flags、adapter、run_query などのコンテキストが利用可能です。モデル依存関係の解決は行われないため、管理系の一括処理やメンテナンスに向きます。
設計の要点は冪等性と安全な引数設計です。dry-run を備え、明示的なスキーマやロールのみを対象にし、実行ログと戻り値を機械可読な形式(JSON)で返すと、オーケストレーションや監査に強くなります。
| コマンド | 目的 | 依存解決/対象 |
|---|---|---|
| dbt run | モデルをMaterializationに従い実行 | DAG解決あり/選択子でモデル対象 |
| dbt build | run+test+snapshot等を包括的に実行 | DAG解決あり/選択子で包括対象 |
| dbt seed | CSVシードのロード | 依存なし/seedファイル対象 |
| dbt run-operation | マクロを直接実行(管理系) | 依存解決なし/マクロのロジック対象 |
operations 実行フロー(概念)
最小テンプレート(戻り値をJSONで返す)
{% macro op_template(required_arg, optional_arg='') %}
{% if required_arg is not string %}
{% do exceptions.raise_compiler_error('required_arg must be string') %}
{% endif %}
{% do log('target: ' ~ target.name ~ ' (' ~ target.type ~ ')', info=True) %}
{% do return({'ok': True, 'arg': required_arg, 'opt': optional_arg}) %}
{% endmacro %}環境ごとにスキーマへの USAGE、テーブル/ビューへの SELECT を付与する運用は典型的な operations の適用先です。Snowflake と Databricks(Unity Catalog 含む)向けの単純化した例を示します。実行前に dry_run で発行SQLを確認できるようにします。
BigQuery では IAM ロール付与が主となるため、同等の処理は GRANT 文ではなくプロジェクト/データセット レベルの権限管理で行うのが一般的です。以下のマクロは Snowflake と Databricks/Spark に限定しています。
grant_usage_and_select マクロ例
{% macro grant_usage_and_select(target_schema, role, dry_run=False) %}
{%- set wh = target.type -%}
{%- set statements = [] -%}
{%- if wh == 'snowflake' -%}
{%- do statements.append('grant usage on schema ' ~ target.database ~ '.' ~ target_schema ~ ' to role ' ~ role) -%}
{%- do statements.append('grant select on all tables in schema ' ~ target.database ~ '.' ~ target_schema ~ ' to role ' ~ role) -%}
{%- do statements.append('grant select on future tables in schema ' ~ target.database ~ '.' ~ target_schema ~ ' to role ' ~ role) -%}
{%- do statements.append('grant select on all views in schema ' ~ target.database ~ '.' ~ target_schema ~ ' to role ' ~ role) -%}
{%- do statements.append('grant select on future views in schema ' ~ target.database ~ '.' ~ target_schema ~ ' to role ' ~ role) -%}
{%- elif wh in ['databricks','spark'] -%}
{%- set cat = target.get('catalog') if target.get('catalog') else target.database -%}
{%- set full_schema = cat ~ '.' ~ target_schema -%}
{%- do statements.append('grant usage on schema ' ~ full_schema ~ ' to ' ~ role) -%}
{%- do statements.append('grant select on all tables in schema ' ~ full_schema ~ ' to ' ~ role) -%}
{%- do statements.append('grant select on all views in schema ' ~ full_schema ~ ' to ' ~ role) -%}
{%- else -%}
{%- do exceptions.raise_compiler_error('Unsupported adapter for this macro: ' ~ wh) -%}
{%- endif -%}
{%- if dry_run -%}
{%- for s in statements %}{% do log(s, info=True) %}{% endfor -%}
{% do return({'executed': False, 'statements': statements}) %}
{%- else -%}
{%- for s in statements %}
{% do run_query(s) %}
{% do log('OK: ' ~ s, info=True) %}
{%- endfor -%}
{% do return({'executed': True, 'count': statements|length}) %}
{%- endif -%}
{% endmacro %}
-- 実行例(CLI)
-- 事前に profiles.yml の prod ターゲットを設定
-- dry-run で確認
-- dbt run-operation grant_usage_and_select --target prod --args '{"target_schema": "analytics", "role": "ANALYST_ROLE", "dry_run": true}'
-- 本実行
-- dbt run-operation grant_usage_and_select --target prod --args '{"target_schema": "analytics", "role": "ANALYST_ROLE"}'検証環境の一時スキーマ作成、検収後のクリーンアップなど、スキーマのライフサイクル操作も operations で自動化できます。blast radius を最小化するため、明示リストのみに作用し、dry-run を通すポリシーにします。
以下はスキーマの create/drop をまとめて行うマクロ例です。多くの DWH で create schema if not exists / drop schema if exists が利用できます。
ensure_schemas マクロ例
{% macro ensure_schemas(schemas=[], action='create', dry_run=False) %}
{%- if schemas is string -%}
{%- set schemas = [schemas] -%}
{%- endif -%}
{%- set stmts = [] -%}
{%- for s in schemas -%}
{%- if action == 'create' -%}
{%- set stmt = 'create schema if not exists ' ~ target.database ~ '.' ~ s -%}
{%- elif action == 'drop' -%}
{%- set stmt = 'drop schema if exists ' ~ target.database ~ '.' ~ s ~ ' cascade' -%}
{%- else -%}
{%- do exceptions.raise_compiler_error("action must be 'create' or 'drop'") -%}
{%- endif -%}
{%- do stmts.append(stmt) -%}
{%- endfor -%}
{%- if dry_run -%}
{%- for s in stmts %}{% do log(s, info=True) %}{% endfor -%}
{% do return({'executed': False, 'statements': stmts}) %}
{%- else -%}
{%- for s in stmts %}{% do run_query(s) %}{% endfor -%}
{% do return({'executed': True, 'count': stmts|length}) %}
{%- endif -%}
{% endmacro %}
-- 実行例
-- dbt run-operation ensure_schemas --target dev --args '{"schemas": ["tmp_feature_a", "tmp_feature_b"], "action": "create", "dry_run": true}'dbt Cloud の Job では、Step に run-operation を追加できます。例: Step1 で権限付与、Step2 で本番パイプライン(dbt build)、Step3 で後片付けといった並びが定番です。スケジュールやトリガにより安定的に実行され、ログ/結果は Cloud 上で確認できます。
CI/CD(GitHub Actions など)や外部オーケストレータ(Airflow, Dagster など)からも、同じ CLI を呼び出せば再現性を保てます。標準出力の JSON を収集し、監査ログに保存しておくと後から検証しやすくなります。
GitHub Actions 例(Snowflake アダプタ)
name: run-operations
on:
workflow_dispatch:
jobs:
op:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dbt core and adapter
run: |
pip install --upgrade pip
pip install dbt-core dbt-snowflake
- name: Run dbt operation (dry-run)
env:
DBT_USER: ${{ secrets.DBT_USER }}
DBT_PASSWORD: ${{ secrets.DBT_PASSWORD }}
run: |
dbt deps
dbt debug --target prod --profiles-dir .
dbt run-operation grant_usage_and_select \
--target prod \
--args '{"target_schema": "analytics", "role": "ANALYST_ROLE", "dry_run": true}'運用系マクロは失敗時の影響が大きくなりがちです。dry-run の実装、対象の明示、実行前ログ、失敗時の早期中断(compiler_error)を基本に据えます。必要に応じてトランザクションでまとめるか、逆に DDL の性質に合わせて小刻みに実行し失敗箇所を特定できるようにします。
入力検証は厳密に行い、環境変数や target による分岐は最小限にします。権限付与は最小権限の原則を守り、将来オブジェクト(future grants など)を適切に使います。
トランザクション適用の簡易ラッパ(対応するDWHのみ)
{% macro run_in_transaction(sqls=[]) %}
{# 注意: 一部DWHはDDLのトランザクションをサポートしません #}
{% do run_query('begin') %}
{% for s in sqls %}
{% do run_query(s) %}
{% endfor %}
{% do run_query('commit') %}
{% do return({'executed': sqls|length}) %}
{% endmacro %}
-- 利用例
-- {% do run_in_transaction(['grant usage on schema DB.SCHEMA to role R', 'grant select on all tables in schema DB.SCHEMA to role R']) %}dbt run-operation で実行されたマクロは、return() に渡したオブジェクトを標準出力に表示します。これを機械可読な JSON にしておくと、外部からの収集・検証が容易です。合わせて log() で人間が読みやすいメッセージも出力します。
CLI 実行結果から JSON 部分のみを抽出し、保存・通知に使う例を示します。環境によっては --quiet オプションを活用し、ノイズの少ない出力にすると扱いやすくなります。
標準出力から JSON を抽出する例(bash)
# dry-run の結果を取得
out=$(dbt --quiet run-operation grant_usage_and_select --args '{"target_schema": "analytics", "role": "ANALYST_ROLE", "dry_run": true}')
# dbt は "The result of this operation was: <JSON>" の形式で出力するため、JSON 部分を抽出
json=$(printf "%s\n" "$out" | sed -n 's/.*The result of this operation was:\s*//p')
# 任意: 整形や保存
printf "%s\n" "$json" | jq .
echo "$json" > operation-result.jsonAnalytics Engineer
問題 1
本番パイプラインの dbt build 実行前に、環境ごとに対象スキーマへ USAGE と SELECT を付与したい。最も運用しやすいアプローチはどれか。
正解: A
権限付与は管理タスクであり DAG 外で安全に実行すべきです。dbt Cloud Job の Step に run-operation を追加し、環境別引数を渡すと、順序やログ、再現性を一元管理できます。pre-hook はモデルごとに走り制御が難しく、外部スクリプトは監査・再現性で不利、seed はデータロード機能であり権限付与は対象外です.
run-operation で使えるコンテキストは?
target(接続/環境)、env_var、flags、adapter、run_query、log、exceptions などが利用できます。モデルの依存解決は行われず、ref/source に依存した実行は基本的に想定しません。
引数はどのように渡すべき? 配列や真偽値は?
--args には JSON/YAML 互換の文字列を渡し、マクロの引数名と一致させます。例: --args '{"schemas": ["a","b"], "dry_run": true}'。マクロ側ではデフォルト値を設定し、型検証を行います。
on-run-start/on-run-end のフックと operations の違いは?
フックは dbt run/build のライフサイクルに結びついた自動実行です。operations は任意タイミングでマクロを単独実行します。順序制御や再実行性、引数の柔軟性が必要な管理タスクは operations が適しています。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
dbt Model の基礎: SQL で定義する変換の最小単位
Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...
dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点
dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...
dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点
dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...
dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト
Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....
dbt_project.yml の読み方:主要設定と命名を最短で掴む
dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...