SIer出身エンジニアのためのdbt入門 ── ストアドプロシージャからdbtモデルへ
はじめに
SIerでストアドプロシージャやバッチ処理を書いていた人にとって、dbtは最もとっつきやすいモダンデータスタックのツールです。
なぜなら、dbtの本質は「SQLファイルをGit管理して、テストとドキュメントを自動生成する仕組み」だからです。SQLが書ければ、dbtは書けます。
この記事では、SIerで馴染みのある概念とdbtの概念を対応させながら、最短で理解するためのガイドを提供します。
ストアドプロシージャ vs dbtモデル
SIer時代の典型的な処理
-- ストアドプロシージャ: 売上集計バッチ
CREATE OR REPLACE PROCEDURE sp_aggregate_sales()
LANGUAGE SQL
AS
$$
BEGIN
-- ステージングテーブルにINSERT
TRUNCATE TABLE stg_sales;
INSERT INTO stg_sales
SELECT
order_id,
customer_id,
CAST(order_date AS DATE) as order_date,
amount
FROM raw_orders
WHERE order_date >= CURRENT_DATE - 30;
-- 集計テーブルにINSERT
TRUNCATE TABLE mart_monthly_sales;
INSERT INTO mart_monthly_sales
SELECT
customer_id,
DATE_TRUNC('month', order_date) as sales_month,
COUNT(*) as order_count,
SUM(amount) as total_amount
FROM stg_sales
GROUP BY customer_id, DATE_TRUNC('month', order_date);
END;
$$;
dbtで書くと
models/staging/stg_sales.sql:
SELECT
order_id,
customer_id,
CAST(order_date AS DATE) as order_date,
amount
FROM {{ source('raw', 'orders') }}
WHERE order_date >= CURRENT_DATE - 30
models/marts/mart_monthly_sales.sql:
SELECT
customer_id,
DATE_TRUNC('month', order_date) as sales_month,
COUNT(*) as order_count,
SUM(amount) as total_amount
FROM {{ ref('stg_sales') }}
GROUP BY customer_id, DATE_TRUNC('month', order_date)
違いは明白です。
-
CREATE PROCEDUREやTRUNCATE + INSERTが不要。SELECT文だけ書けばいい -
{{ source() }}でソーステーブルを参照 -
{{ ref() }}でモデル間の依存関係を自動解決 - 各モデルが独立したSQLファイルとしてGit管理される
JP1のジョブネット vs dbtのDAG
SIerでJP1のジョブネットを設計した経験がある人なら、dbtのDAG(有向非巡回グラフ)はすぐ理解できます。
JP1では「ジョブA → ジョブB → ジョブC」の実行順序をGUIで定義しますが、dbtでは{{ ref() }}を書くだけで依存関係が自動的に構築されます。
-- JP1のジョブネット(イメージ)
ジョブA: raw_orders → stg_orders
ジョブB: stg_orders → mart_daily_sales (ジョブAの後に実行)
ジョブC: stg_orders → mart_customer_summary(ジョブAの後に実行)
-- dbtの場合
-- stg_orders.sql に {{ source('raw', 'orders') }} と書く
-- mart_daily_sales.sql に {{ ref('stg_orders') }} と書く
-- mart_customer_summary.sql に {{ ref('stg_orders') }} と書く
-- → dbt が自動的に実行順序を解決する
dbt run を実行するだけで、依存関係に基づいた正しい順序でモデルがビルドされます。
結合テスト vs dbt test
SIerではテスト仕様書をExcelで作成して手動でテストしていたものが、dbtではYAMLで定義して自動実行されます。
models/staging/schema.yml:
version: 2
models:
- name: stg_sales
description: "クレンジング済みの売上データ"
columns:
- name: order_id
description: "注文ID(ユニーク)"
tests:
- unique
- not_null
- name: customer_id
description: "顧客ID"
tests:
- not_null
- relationships:
to: ref('stg_customers')
field: customer_id
- name: amount
description: "注文金額(正の値)"
tests:
- not_null
- dbt_utils.accepted_range:
min_value: 0
dbt test を実行すると、定義したテストが自動的に実行されます。
-
unique: ユニーク制約のチェック -
not_null: NULL値がないことのチェック -
relationships: 参照整合性のチェック(外部キー制約相当) -
accepted_range: 値の範囲チェック
SIerで「NULLチェック」「一意性チェック」「参照整合性チェック」をSQLで手書きしていたものが、YAML数行で定義できます。
設計書 vs dbt docs
dbt docs generate を実行すると、モデル間の依存関係(リネージ)、テーブル定義、カラム説明がWebページとして自動生成されます。
Excel方眼紙で設計書を書く時代は終わりです。
最速で始める方法
- dbt Cloud の無料アカウントを作成
- Snowflakeの無料トライアルと接続
- 公式チュートリアル jaffle_shop を実施
- 自分のプロジェクトで小さなモデルを1つ作ってみる
SQLが書ける人なら、チュートリアルは2〜3時間で完了します。
まとめ
| SIerの概念 | dbtの概念 |
|---|---|
| ストアドプロシージャ | dbtモデル(.sqlファイル) |
| TRUNCATE + INSERT |
dbt run(自動でCTAS/マージ) |
| JP1ジョブネット | DAG({{ ref() }}で自動構築) |
| テスト仕様書 + 手動テスト |
dbt test(YAMLで定義、自動実行) |
| Excel設計書 |
dbt docs(自動生成) |
| Git管理なし | 全モデルがGit管理 |
SIerの経験がある人にとって、dbtは「今までやっていたことの効率化ツール」です。新しい概念を学ぶというより、既存の知識の延長で理解できます。
筆者はSIerから事業会社のデータエンジニアに転職し、Snowflakeベースのデータ基盤を運用しています。
Discussion