dbt はフォルダ構成と命名規約がそのまま開発体験や運用コストに跳ね返ります。特に models・seeds・macros のレイアウトは、DAG の見通し、レビュー容易性、CI 選択性に直接影響します。
この記事では、安定機能を前提に公式ドキュメントの挙動に沿って、最小驚きで運用できる構造を提示します。最後に資格試験向けのポイントも織り込みます。
dbt は「ファイル配置 = リソース定義」という流儀です。models は SQL からデータベースオブジェクトを作り、seeds は CSV をテーブル化し、macros は Jinja でロジックを再利用します。配置が曖昧だと、DAG の境界が崩れ、レビューと影響範囲の切り分けが困難になります。
資格試験でも、staging → intermediate → marts の分離、seeds の用途、macros の役割とスコープが頻出です。まずは役割と粒度を固定し、dbt_project.yml で一貫したスキーマ付与とタグ運用を行いましょう。
最小驚き原則に従い、models を層とドメインで二段分け、seeds は用途別、macros は汎用ユーティリティとアダプタ分岐を分けます。各層ごとにスキーマとマテリアライズを dbt_project.yml で明示し、CI 選択子やタグと連動させます。
下のツリーは小規模から中規模まで伸びる汎用構成です。stg/int/marts の3層、seeds は mappings などの機能別、macros は util と tests を分離しています。
| 項目 | models | seeds | macros |
|---|---|---|---|
| 主目的 | SQL でビュー/テーブル等のモデルを作成 | 小規模な参照データを CSV からテーブル化 | Jinja ロジックの再利用・抽象化 |
| 定義場所 | models/ | seeds/ | macros/ |
| DB 実体 | view/table/incremental/ephemeral | 通常はテーブル | なし(コンパイル時に展開) |
| 代表コマンド | dbt run / build | dbt seed | dbt run-operation(任意) |
| テスト適用 | generic/singular いずれも可 | generic 可(主に主キー/参照整合) | 対象外 |
| 落とし穴 | 層間混在でDAG肥大・循環 | 大容量CSV・型未指定・権限不足 | 副作用のあるマクロ乱用 |
標準的な dbt プロジェクト構造と DAG の層分け
project/
dbt_project.yml
packages.yml
models/
staging/
src__app/
stg_app__users.sql
stg_app__orders.sql
intermediate/
int__orders_enriched.sql
marts/
sales/
dim_customer.sql
fct_order.sql
seeds/
mappings/
country_codes.csv
macros/
util/
surrogate_key.sql
cast_to_boolean.sql
tests/
relationships_if.sql
snapshots/
app/
orders_snapshot.sql
tests/
generic/
not_null_if.sql
DAG(概念):
[raw.sources] --> [staging: stg_*] --> [intermediate: int_*] --> [marts: dim_*/fct_*]
dbt_project.yml とモデル/マクロ例
# dbt_project.yml (抜粋)
name: my_project
version: 1.0.0
profile: my_profile
model-paths: ["models"]
seed-paths: ["seeds"]
macro-paths: ["macros"]
snapshot-paths: ["snapshots"]
test-paths: ["tests"]
models:
+materialized: view
my_project:
staging:
+schema: stg
+tags: ["staging"]
intermediate:
+schema: int
+tags: ["transform"]
marts:
+schema: mart
+materialized: table
sales:
+schema: mart_sales
seeds:
my_project:
+schema: seed
+quote_columns: false
mappings:
country_codes:
+column_types:
country_code: varchar(2)
country_name: varchar(64)
# macros/util/surrogate_key.sql
{% macro surrogate_key(cols) %}
md5({{ cols | map('string') | join(" || '-' || ") }})
{% endmacro %}
# models/marts/sales/dim_customer.sql
{{ config(materialized='table') }}
with src as (
select * from {{ ref('int__orders_enriched') }}
), dedup as (
select distinct customer_id, customer_name from src
)
select
{{ surrogate_key(["customer_id"]) }} as customer_sk,
customer_id,
customer_name
from dedup;プロジェクト設定は階層適用が基本です。上位でデフォルト、下位ディレクトリで差分を上書きすることで、層ごとのスキーマ、マテリアライズ、タグを安定させます。materialized のデフォルトは view、marts のみ table とするのが保守的です。
seeds は schema、quote_columns、column_types を明示。特に列型はターゲット DWH ごとのデフォルト型に依存しないよう、主キーやコード列に長さを付けます。
ファイル名は層を示す接頭辞で統一します。stg_ は生データの型揃え・列名正規化、int_ は結合・ビジネスロジックの集約、dim_ と fct_ は最終提供物です。層を跨いだ参照を避け、ref は一層下流のみを指すのが安全です。
スキーマは層単位に分けると、テーブル一覧や権限設計が明確になります。DAG の可視化では、層間のエッジが右肩上がりになるように循環を防ぎます。
seeds は小さな参照テーブル向けです。コード体系、ラベル、しきい値など、変更頻度は低いが JOIN されるデータを CSV 管理します。dbt seed でデータベースにテーブルとしてロードされ、モデルと同様にテストを適用できます。
落とし穴はサイズ・型・変更管理です。大容量 CSV は適しません。column_types で明示型を付け、リポジトリのレビューで差分を確認。運用では権限とロケール(区切り・改行コード)にも注意します。
macros はコンパイル時に SQL を生成する仕組みです。ビジネスロジックを隠しすぎず、SQL 可読性が落ちない粒度で関数化します。サロゲートキー生成や型変換、条件付きテストなどが好例です。
アダプタ差異は dispatch で吸収できますが、安定運用の観点からは汎用化しすぎず、ターゲット DWH 毎の軽量分岐に留めるとデバッグが容易です。外部パッケージ(macros)の導入時はバージョンを固定します。
Analytics Engineer 試験では、models/seeds/macros の使い分け、dbt_project.yml の階層設定、ref/source、テストの適用範囲が狙われます。特に seeds の用途、モデル層の分離、マクロの責務は押さえます。
実務では CI セレクタ(タグ/パス)で部分ビルド、スキーマ分離で権限とカタログを整理、レビューでは層逸脱や過剰マクロ化をチェックします。
Analytics Engineer
問題 1
組織で国コードの標準化(ISO2→表示名)を行いたい。変更は四半期に数件、開発レビューで追跡したい。dbt で最も適切な実装はどれか。
正解: A
小規模・低頻度更新・レビュー追跡という要件には seeds が最適。CSV 管理で差分がレビューでき、dbt seed でテーブル化できる。マクロへのハードコードは可観測性と変更容易性に欠け、手動 INSERT は反復可能性が低い。source は外部実体がある前提で本件には過剰。
seeds はどの程度のサイズまでが現実的ですか?
実装上の上限は倉庫や実行環境に依存しますが、運用観点では数万行・数MB 程度までに留めるのが無難です。大きいものは外部テーブル化し、source 定義で管理してください。
層を跨いで stg から直接 dim_ に JOIN しても良いですか?
避けるべきです。stg → int → dim/fct の一方向を守ると、依存関係が単純化し、テストと所有権の分離、ビルド時間の最適化に寄与します。
macros にビジネスロジックをどこまで入れて良いですか?
SQL の可読性が保てる範囲で、汎用ユーティリティ(キー生成・型変換・条件付きフィルタ)中心に留めるのが安全です。複雑な集計ロジックはモデルとして明示し、テスト可能性を確保してください。
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_project.yml の読み方:主要設定と命名を最短で掴む
dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...
dbt profiles.yml と接続管理:環境別のベストプラクティス
dbt Core/Cloud で profiles.yml を用いて dev/stg/prod など環境別に接続を切り替...