LESSON 30分

dbtの高度な機能

田中VPoE「dbtの基本は身についたね。ここからは、実運用で必要になる高度な機能を学ぼう。マクロ、パッケージ、hooks、そして運用のベストプラクティスだ。」

あなた「マクロってJinjaテンプレートのことですよね?SQLの中でプログラミングみたいなことができるんですか?」

田中VPoE「その通り。DRY原則を守りながら、再利用可能なSQL部品を作れるんだ。ただし、使いすぎると可読性が下がるから、バランスが大事だよ。」

Jinjaテンプレートとマクロ

Jinjaの基本構文

dbtではJinjaテンプレートエンジンを使って、SQLを動的に生成できます。

-- 変数の参照
{{ var('start_date', '2024-01-01') }}

-- 条件分岐
{% if target.name == 'prod' %}
    -- 本番環境のみの処理
{% endif %}

-- ループ
{% for status in ['pending', 'completed', 'cancelled'] %}
    SUM(CASE WHEN order_status = '{{ status }}' THEN 1 ELSE 0 END)
        AS {{ status }}_count
    {% if not loop.last %},{% endif %}
{% endfor %}

カスタムマクロの作成

-- macros/cents_to_dollars.sql
{% macro cents_to_dollars(column_name) %}
    CAST({{ column_name }} AS NUMERIC) / 100
{% endmacro %}
-- models/staging/stg_payments.sql
SELECT
    payment_id,
    {{ cents_to_dollars('amount_cents') }} AS amount,
    {{ cents_to_dollars('fee_cents') }} AS fee
FROM {{ source('raw', 'payments') }}

実用的なマクロ例

-- macros/generate_surrogate_key.sql
{% macro generate_surrogate_key(field_list) %}
    TO_HEX(MD5(CONCAT(
        {% for field in field_list %}
            COALESCE(CAST({{ field }} AS STRING), '_null_')
            {% if not loop.last %}, '|', {% endif %}
        {% endfor %}
    )))
{% endmacro %}
-- macros/date_spine.sql
{% macro date_spine(start_date, end_date) %}
    SELECT date
    FROM UNNEST(
        GENERATE_DATE_ARRAY(
            '{{ start_date }}',
            '{{ end_date }}',
            INTERVAL 1 DAY
        )
    ) AS date
{% endmacro %}

パッケージ管理

packages.ymlの設定

# packages.yml
packages:
  - package: dbt-labs/dbt_utils
    version: [">=1.0.0", "<2.0.0"]

  - package: dbt-labs/dbt_date
    version: [">=0.7.0", "<1.0.0"]

  - package: calogica/dbt_expectations
    version: [">=0.8.0", "<1.0.0"]

  - package: elementary-data/elementary
    version: [">=0.13.0", "<1.0.0"]
# パッケージのインストール
dbt deps

主要パッケージ

パッケージ用途主要機能
dbt_utilsユーティリティsurrogate_key, pivot, union_relations
dbt_expectationsデータ品質テストGreat Expectations風のテスト
dbt_date日付操作date_spine, fiscal_year
elementary可観測性異常検知、テスト結果ダッシュボード
codegenコード生成YAMLの自動生成

Hooks(フック)

特定のタイミングで追加SQLを実行します。

# dbt_project.yml
on-run-start:
  - "CREATE SCHEMA IF NOT EXISTS {{ target.schema }}_audit"

on-run-end:
  - "{{ log_run_results() }}"

models:
  netshop:
    marts:
      +post-hook:
        - "GRANT SELECT ON {{ this }} TO GROUP analysts"
フック実行タイミング
on-run-startdbt run の開始前
on-run-enddbt run の完了後
pre-hookモデルのビルド前
post-hookモデルのビルド後

セレクター構文

特定のモデルだけを実行する強力な構文です。

# 特定モデルとその上流すべて
dbt run --select +mart_customer_ltv

# 特定モデルとその下流すべて
dbt run --select stg_orders+

# タグ指定
dbt run --select tag:daily

# 変更があったモデルのみ(slim CI)
dbt run --select state:modified+ --state ./prod-manifest
構文意味
model_name指定モデルのみ
+model_name指定モデルとその上流すべて
model_name+指定モデルとその下流すべて
+model_name+上流と下流すべて
tag:dailyタグがdailyのモデル
path:models/marts特定パス配下

運用のベストプラクティス

1. 命名規則

要素規則
Stagingモデルstg_{source}_{entity}stg_mysql_orders
Intermediateモデルint_{entity}_{verb}int_orders_enriched
Martモデルmart_{domain}_{entity}mart_finance_daily_revenue
マクロ{verb}_{noun}generate_surrogate_key
テストassert_{condition}assert_revenue_positive

2. CI/CDパイプライン

# .github/workflows/dbt_ci.yml
name: dbt CI
on:
  pull_request:
    paths: ['models/**', 'macros/**', 'tests/**']

jobs:
  dbt-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install dbt
        run: pip install dbt-bigquery
      - name: dbt deps
        run: dbt deps
      - name: dbt build (modified only)
        run: dbt build --select state:modified+ --state ./prod-manifest

3. 環境分離

# profiles.yml
netshop:
  target: dev
  outputs:
    dev:
      type: bigquery
      project: netshop-dev
      dataset: "dbt_{{ env_var('USER') }}"
    prod:
      type: bigquery
      project: netshop-prod
      dataset: analytics

まとめ

項目ポイント
JinjaマクロSQL部品の再利用、DRY原則の適用
パッケージdbt_utils等のコミュニティ資産を活用
Hooks実行前後の追加処理(権限付与等)
セレクター部分実行、CI/CDでの差分ビルド
運用命名規則・CI/CD・環境分離が重要

チェックリスト

  • Jinjaテンプレートの基本構文を理解している
  • カスタムマクロを作成できる
  • パッケージのインストールと利用方法を知っている
  • セレクター構文を使って部分実行ができる
  • CI/CDパイプラインの構成を理解している

次のステップへ

dbtの高度な機能を学びました。次は演習で、NetShop社のデータ変換パイプラインをdbtで実際に構築してみましょう。


推定読了時間:30分