source 定義:外部データとの契約を書く
Stage 1 — 第4章 | dbt入門カリキュラム 推定学習時間:30〜40分 | 難易度:★★★☆☆
この章で学ぶこと
staging モデルの SQL は、多くの場合 {{ source('ソース名', 'テーブル名') }} から始まります。
これは「生 SQL で FROM app_db.orders と書く」のではなく、dbt プロジェクトの外にある表 を YAML で宣言してから参照する、という作法です。
この章では、まず source 定義(なぜ YAML か、ref() との違い、description に何を書くか)を整理します。
最後に、DS Playground の dbt プロジェクトが どういう方針で source を書いているか を短く見ます。
この章を終えると、こんなことができるようになります:
sources:YAML が 入力契約 である理由を説明できるsource()とref()を 使い分け られる- source の
descriptionに テーブルの性質(最新状態か、イベント履歴か)を書く意味を説明できる - 分析用 DB 接続を 読み取り専用 にする理由を説明できる
source() とは何か
dbt プロジェクトのモデルは、大きく 2 種類の入力 を持ちます。
- プロジェクト外の表 … アプリ DB、SaaS、ログ基盤など、dbt が作っていない表
- プロジェクト内の他モデル … すでに dbt が定義した staging / intermediate / marts
前者は source()、後者は ref() で参照します。
-- プロジェクト外(アプリ DB 等)
select *
from {{ source('app', 'orders') }}
-- プロジェクト内(dbt モデル)
select *
from {{ ref('stg_orders') }}
source() を使うと、「この Transform はどの外部表から始まるか」 がコードと YAML の両方に残ります。
個人の BI クエリのように FROM 句に生の表名を直書きすると、入力の一覧や意味がプロジェクト外に散らばりやすくなります。
sources は アプリ DB が正本(SSOT) であり、dbt はその 読み取り側 という関係もここで固定されます。 データマネジメント入門の SSOT で学んだ「正本は一箇所」を、Transform の入口で実装している、と考えるとよいです。
sources YAML の書き方
source は _sources.yml のような YAML に宣言します。構造はシンプルです。
version: 2
sources:
- name: app # source() の第 1 引数
description: "本番アプリ DB の public スキーマ"
database: analytics_raw
schema: public
tables:
- name: orders
description: "注文ヘッダ。1 行 = 1 注文。"
- name: order_events
description: "注文に関するイベント履歴。append-only。"
| フィールド | 意味 |
|---|---|
name |
source('app', ...) の 'app' 部分 |
database / schema |
接続先の論理位置(環境ごとに切り替えることも多い) |
tables[].name |
source(..., 'orders') の第 2 引数 |
tables[].description |
その表が何を表すか(後述) |
接続パスワードや API キーは YAML に書きません。profiles.yml や CI の環境変数側に置き、repo には秘密を載せないのが通常です。
source() と ref() — lineage の入口
- sources ノード … アプリ DB など dbt の外
- model ノード …
ref()でつながる dbt の内側
dbt docs の lineage では、この境界がはっきり見えます。 「ダッシュボードの数字はどの生表に遡るか」を説明するとき、sources が起点 になります。
staging では source()、intermediate / marts では基本的に ref() だけ、という 層ごとの約束 がよく使われます。
staging で ref() だけにすると、外部入力が見えにくくなります。逆に marts で source() を直叩きすると、依存がバラけます。
description に書くべきこと
source YAML の description は、飾りではなく 設計メモ です。
特に次の区別は、下流の KPI 定義に直結します。
最新状態(current-state)の表 … 同じキーの行が更新され、今の状態 が 1 行に載る。
イベント履歴(event log)の表 … 行が append され、いつ何が起きたか が残る。
この違いを source 段階で書いておくと、「この KPI は最新正答率か、初回正解率か」のような 取り違え を防げます。 staging が薄い設計ほど、ソースの意味 を YAML に残す価値が大きいです。
列名のリネームや型変換は staging SQL の仕事ですが、「この表は履歴か、スナップショットか」は source の description に書く、という分担が一般的です。
分析接続は読み取り専用に
dbt は Transform の結果を 分析用スキーマ(DS Playground では analytics)に build します。
一方、アプリ DB(OLTP)の表は SELECT だけ するのが原則です。
分析パイプラインにアプリと同じ 強権限(全表書き込み・RLS バイパスなど)を渡すと、Transform のバグや設定ミスが 本番データを壊す リスクにつながります。 そのため、dbt 用 DB ユーザーは 読み取り専用 にし、書き込み先を分析専用スキーマに限定する、という構成が一般的です。
アプリ ──書込──> OLTP 表(正本)
^
| SELECT only
dbt ────────────────┴──> 分析用 schema(dbt が CREATE)
データマネジメント入門の権限 で学んだ 最小権限 と同じ発想です。
DS Playground ではどうしているか
DS Playground の dbt プロジェクトは、Supabase の public スキーマ上のアプリ表を source('supabase', ...) で読みます。
YAML 側では name: supabase と宣言し、staging モデル stg_supabase__* がそれぞれ 1 source 表に対応します。
方針の要点だけ挙げます(全表の一覧は YAML 正本に任せ、ここでは覚えなくてよいです)。
- アプリ DB が正本、dbt は read-only で読む
- 加工結果は
analyticsスキーマに build する - source の
descriptionに、表が 最新状態かイベント履歴か を書く - 認証用の
auth.users等は analytics から直接読まず、分析に必要な同意・行動データ 経由で母集団を定義する
staging SQL の典型形は次のとおりです。
select
user_id,
consent_type,
captured_at,
cast(captured_at as date) as captured_date
from {{ source('supabase', 'consents') }}
where user_id is not null
consents のような 同意履歴 を会員数の proxy に使う、といった 定義の選択 は Stage 3 以降で詳しく読みます。
この章で押さえるのは、「外部表は source で宣言し、staging はそこから始める」という 構造 です。
体系コラム:カリキュラム上の位置づけ
| 項目 | 内容 |
|---|---|
| Stage / 章 | Stage 1 — 第4章 |
| 今回の論点 | 入力契約(sources)と read-only 接続 |
| 前章との接続 | dbt project 構成 |
| 次章への伏線 | staging:ソース意味を残す薄い変換 |
まとめ
sources は FROM 句に書く生の表名ではなく、外部データへの読み取り契約とメタデータ です。
source() で入口を固定し、下流は ref() でつなぐ——この境界が、dbt プロジェクトの最初の設計判断のひとつです。
関連教材
- 前章: dbt project 構成
- 次章: staging:ソース意味を残す薄い変換
- 関連(DM): メタデータと来歴
確認問題
問題 1
from {{ source('app', 'orders') }} と from {{ ref('stg_orders') }} の違いとして 最も適切 なのはどれですか。
A. どちらも同じで、好みで置き換え可能
B. source() は dbt 外部 の宣言済み表、ref() は dbt 内部 モデルへの依存
C. source() は marts 専用、ref() は staging 専用
D. ref() だけが lineage に現れる
正解: B
解説: sources はプロジェクト外の入力、ref はプロジェクト内の依存です。staging は通常 source() を読み、下流は ref('stg_...') を読みます。
問題 2
分析用 dbt 接続を 読み取り専用(SELECT のみ) にする主な理由はどれですか。
A. dbt が INSERT をサポートしないから
B. Transform のミスでも OLTP の正本表を UPDATE/DELETE しないため
C. BI ツールが書き込みを禁止しているから
D. YAML に書けないから
正解: B
解説: 書き込み先は分析用スキーマに限定し、OLTP は読むだけ、という分離が一般的です。
問題 3
source YAML の description に 「append-only のイベント履歴」 と書く主な理由はどれですか。
A. SQL を短くするため
B. 下流で「最新状態」と「履歴」を取り違えないため
C. BI ツールの表示色を変えるため
D. seed ファイルの行数を減らすため
正解: B
解説: テーブルの性質は KPI 定義に効きます。イベント履歴と最新状態表を source 段階で区別しておくと、下流の staging 設計がぶれにくくなります。
用語メモ(この章)
| 用語 | 意味(この章での使い方) |
|---|---|
| source | dbt 外部の生データ表(YAML で宣言) |
source() |
外部表を参照する dbt マクロ |
ref() |
プロジェクト内の他モデルを参照する dbt マクロ |
| read-only | OLTP 表は SELECT のみ。書き込みは分析用 schema へ |