dbtではモデルを役割ごとに層分割することで、変更の影響範囲を小さくし、テスト容易性と運用性を高めます。本稿ではstaging、intermediate、martsの3層を中心に、責務の切り分けと設計原則を解説します。
dbt Analytics Engineerの試験対策観点では、各層で"やってよいこと/やってはいけないこと"を即答できること、命名規約とテストの配置基準を説明できることが重要です。
3層分割の主目的は、データの正規化・統一化(staging)、横断的な整合化と前処理(intermediate)、分析消費に最適化された事実・次元(marts)という処理責務を明確にし、欠陥の局所化と変更容易性を得ることです。公式ドキュメントでも、モデルの粒度・責務・命名の一貫性が保守性を高めるとされています。
層をまたぐルールは単純です。下位層は上位層に依存しない。上位層ほどビジネス用途に近い表現を持つが、集計・派生指標の重複定義は避ける。テストは層に応じた性質で配置する(stagingは構造・一意性、intermediateは関係整合、martsはビジネス検証)。
| レイヤー | 主目的 | 入力/出力 | 集約粒度 |
|---|---|---|---|
| staging | 型揃え・命名統一・重複排除 | 入力: source() / 出力: stg_* | 原データに限りなく近い行粒度 |
| intermediate | 横断結合・整合・準正規化 | 入力: stg_* / 出力: int_* | 用途に依るが基本は詳細粒度 |
| marts | 消費最適化(事実/次元、スター型) | 入力: int_* / 出力: dim_*, fct_* | 分析・可視化に適した粒度(しばし詳細) |
3層モデルのデータフロー(概念図)
stagingは外部システム差異を吸収し、以降の層が"同じ前提"で扱えるようにします。許容される処理は、型変換、命名の正規化、トリムや単純な正規化、重複排除、レコード有効判定などです。ビジネス集計や指標は含めません。
テーブルは原則ソースごとに1:1で用意し、列名は分析で使う最終名に寄せます。ソース整合性はsource freshnessや受け入れ値テストで担保します。
stg_orders.sql と schema.yml の例
-- models/staging/app/stg_orders.sql
with src as (
select * from {{ source('app', 'orders') }}
),
renamed as (
select
cast(id as bigint) as order_id,
cast(customer_id as bigint) as customer_id,
cast(total_amount as numeric) as amount,
date_trunc('second', created_at) as created_at,
coalesce(status, 'unknown') as status
from src
),
dedup as (
select *
from (
select *, row_number() over (partition by order_id order by created_at desc) as rn
from renamed
) t where rn = 1
)
select * from dedup;
# models/staging/app/stg_orders.yml
version: 2
models:
- name: stg_orders
columns:
- name: order_id
tests:
- not_null
- unique
- name: customer_id
tests:
- not_null
- name: status
tests:
- accepted_values:
values: ['paid','cancelled','pending','unknown']
# models/staging/app/stg_customers.yml(関係テストは中間層で)
# relationships テストは int 層で customer_id の参照整合に用いるのが安全です。intermediateは、stagingで整形済みのエンティティを横断的に結合し、キー整合やビジネスに依存し過ぎない前処理を集約します。異なるソースからの顧客IDマッピング、重複顧客の統合、イベントとディメンションの結合などを担います。
ここでは過度な集計や指標計算は避け、最終martsでの再利用可能性を意識します。スナップショット起点の有効期間の展開、サロゲートキーの安定化、結合条件の標準化を置くのが典型です。
martsは分析・可視化・配信(exposures)に最適化された最終形です。スター型(事実と次元)でモデル化し、ファクトはイベントやトランザクションの明細、次元はマスタやスローリーチェンジング(SCD)を担います。
派生指標の定義は重複を避け、中心的な事実テーブルに対する計算は可能ならビューやモデルとして一元化します。マテリアライゼーション選択はワークロードや更新頻度に合わせ、増分テーブルの再計算境界を明確にします。
命名は層・ドメイン・エンティティを接頭辞と順序で明示し、参照規約を一定に保ちます。テストは層ごとに厳格度を変え、失敗時の影響面がわかるように配置します。依存はref()/source()で明示し、上位層から下位層への参照を禁じます。
モデル契約(contracts)やカラム記述は、スキーマの逸脱を早期に検出するのに有効です。環境やdbtのバージョンによりサポート状況が異なるため、導入時は使用中のdbt Core/Cloudのドキュメントで確認してください。
試験では"どの層で何をやるか"が頻出です。例えば、stagingでSUM集計を行うのは誤り、intermediateはキー整合や期間展開、martsは事実/次元と指標の最終定義という区別を押さえます。
実務では、指標が複数場所に定義される重複が最大のコスト源です。定義の所在をmarts側の単一モデルに寄せ、テストで逸脱を検知する流れを確立しましょう。増分モデルは便利ですが、再計算範囲や自然キーの重複規則を曖昧にすると品質を損ねます。
Analytics Engineer
問題 1
受注データを集計し“月次売上”を作成したい。dbtの3層モデルに従う場合、適切な配置はどれか。
正解: C
stagingは型・命名・重複の吸収のみ、intermediateは結合や整合の集約が中心で過度な集計は避ける。消費最適化と指標の一元化はmartsの責務であり、詳細粒度のfct_ordersを作成し、その上で月次集計(派生marts)を定義するのが正しい。
DatabricksのMedallion(Bronze/Silver/Gold)とdbtのstaging/intermediate/martsは対応しますか?
概念的には近いです。BronzeはRAW/ingest、Silverは整形と統合(dbtのstaging+intermediateに相当)、Goldは消費最適化(marts)に対応します。ただし実装は基盤依存なので、各層の責務を明確化した上でマッピングしてください。
relationshipsテストはstagingとintermediateのどちらで書くべきですか?
外部参照の整合はintermediateでの検証が適切です。stagingはソース1:1で整形する段階のため、参照整合の責務を負わせると役割が混ざります。stagingではnot_null/unique/accepted_valuesを中心に配置します。
モデル契約(contracts)の導入タイミングは?
スキーマがある程度安定し、下流影響の可視化体制(CI/CDやテスト)が整った段階が目安です。環境とdbtのバージョンによりサポート内容が異なるため、導入前に使用中の公式ドキュメントで機能範囲と互換性を確認してください。
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)、設定優先度...