ふくふくHukuhuku Inc.
EP.05dbt 10分公開: 2026-05-10

materialization 4種の使い分け:view / table / incremental / ephemeral

model がどう DWH に物理化されるかを決める materialization。性能・コスト・鮮度のバランスで選ぶ判断軸。incremental は EP.11 で深掘り、本記事は 4 種の比較。

#dbt#materialization#view#table#incremental
シェア

materialization は「model の がどう に物理化されるか」を決める設定。`view` `table` `incremental` `ephemeral` の 4 種から選びます。

4 種の挙動と選び方

種類毎回の挙動ストレージクエリ速度向く用途
viewVIEW として作成、参照時に裏の SQL 実行ほぼ 0遅い (毎回計算)staging、軽量変換
tableテーブルを毎回 DROP & CREATE高い速いmarts、 が直接参照
incremental新規/更新分のみ INSERT/MERGE高い速い + ビルド速い大規模イベントログ
ephemeral下流の CTE として展開、テーブル化なし0下流に依存再利用される共通変換

1. view ── 軽量でいつでも最新

config で view を指定
SQL
{{ config(materialized='view') }}
SELECT  charge_id,  customer_id,  amount,  charged_atFROM {{ source('stripe', 'charges') }}WHERE status = 'succeeded'
  • 長所: ビルド速い、ストレージ消費なし、常に最新
  • 短所: 参照のたびに裏の SELECT 全実行、 ダッシュ向きでない
  • 典型用途: staging 全般、軽い rename/cast のみのモデル

2. table ── 速さ最優先

table materialization
SQL
{{ config(    materialized='table',    cluster_by=['date', 'customer_id']  -- BigQuery のクラスタリング) }}
SELECT  DATE(charged_at) AS date,  customer_id,  SUM(amount) AS daily_revenueFROM {{ ref('stg_stripe__charges') }}GROUP BY 1, 2
table の典型問題

毎回フルリビルドするため、ソースが大きいと コスト×時間が跳ねる。100 万行レベルなら問題ないが、1 億行を超え始めたら incremental を検討する。

3. incremental ── 大規模ログの差分更新

incremental の最小例
SQL
{{ config(    materialized='incremental',    unique_key='event_id',    on_schema_change='sync_all_columns') }}
SELECT  event_id,  user_id,  event_type,  occurred_atFROM {{ source('events', 'raw') }}
{% if is_incremental() %}  -- 初回フルビルド時はこのブロックは無視される  WHERE occurred_at > (SELECT MAX(occurred_at) FROM {{ this }}){% endif %}

`is_incremental()` は「過去にビルドされていて差分実行中」かを返す Jinja 関数。初回または `--full-refresh` 時は false。incremental の差分更新パターンは EP.11 で深掘り予定。

4. ephemeral ── テーブルにせず CTE 展開

ephemeral model
SQL
-- models/intermediate/int_orders__cleaned.sql{{ config(materialized='ephemeral') }}
SELECT  order_id,  customer_id,  amount,  COALESCE(refund_amount, 0) AS refund_amountFROM {{ ref('stg_orders') }}WHERE deleted_at IS NULL

ephemeral model を `ref()` した は、下流で CTE として展開される。テーブル化されないので ストレージ 0、ただし下流での実行時間が長くなる複数の下流で同じ計算をする場合は table or view にした方が良い。

判断フロー

decision tree
Text
Q1. 行数は?├─ 〜100万行 → table か view (頻度で決める)├─ 100万〜1億行 → table か incremental└─ 1億行〜  → incremental ほぼ必須
Q2. 直接参照される?├─ BI ダッシュから直接 → table か incremental└─ 他 model からだけ → view (軽い) or ephemeral (再利用)
Q3. 鮮度要件は?├─ 即時最新が必要 → view├─ 1時間遅れOK → incremental (頻繁)└─ 1日遅れOK → table (1日1回 full)

デフォルト materialization のプロジェクト設定

dbt_project.yml で配下のデフォルト指定
YAML
# dbt_project.ymlmodels:  analytics:    staging:      +materialized: view        # staging はすべて view    intermediate:      +materialized: ephemeral    marts:      +materialized: table       # marts はすべて table      finance:        +materialized: incremental  # finance だけは incremental

次の話

EP.06 では dbt のテスト機能 (4 つの組込み + custom) を扱います。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp