dbt

dbt の ephemeral マテリアライゼーション徹底解説: CTE 的な中間ノードを正しく使い分ける

2026-04-19
NicheeLab編集部

ephemeral は、dbt のマテリアライゼーションの一種で、モデルをデータベースに永続化しません。参照先のモデル側の SQL に CTE として差し込まれるため、軽量な中間変換や一時的な整形によく適します。

この記事では、ephemeral の仕組み、他マテリアライゼーションとの違い、設計上の判断軸、実装・デバッグ方法、試験で問われやすいポイントをまとめます。内容は dbt の公式ドキュメントに沿った安定的な概念を前提にしています。

ephemeral の基本: CTE 的中間ノード

ephemeral は、ref で参照された側のモデルを、参照するモデルの SQL 内に CTE(またはサブクエリ相当)としてインライン化します。つまり、ephemeral 自体はデータベース上にテーブルやビューとしては作られません。ビジュアライゼーションツールや他システムから直接参照することはできず、あくまで参照する最終モデルの一部として実行されます。

軽量な整形・フィルタ・列追加などの中間処理で、かつ複数モデルから広く再利用しないケースに向いています。重い集計や広いテーブルを多数の下流から参照する場合は、view/table/incremental の方がメンテナンスや性能面で有利です。

  • 中間処理を物理化せず、参照側にインライン化
  • BI から直接クエリ不可(永続リレーションを作らない)
  • 小規模・単一消費者向けの部品化に最適
  • 重い処理や多消費者には view/table を選択
マテリアライゼーション永続性コンパイル結果実行の単位
ephemeral非永続参照側 SQL の CTE へインライン参照モデルの1本のクエリ内で実行
view永続(論理)CREATE VIEW と SELECT各 SELECT 実行時に評価
table永続(物理)CREATE TABLE AS SELECTdbt 実行時に作成・更新
incremental永続(差分更新)MERGE/INSERT による差分反映dbt 実行時に差分のみ更新

ephemeral の依存関係とインライン化イメージ

orders_ephemeralmaterialized: eph.payments_ephemeralmaterialized: eph.marts.fct_orderstableephemeral モデルは参照側の CTE として展開され、table 化された下流モデルに取り込まれる
-- 参照側での実行時イメージ(概念)
WITH orders_ephemeral AS (...),
     payments_ephemeral AS (...)
SELECT ...
FROM orders_ephemeral
LEFT JOIN payments_ephemeral ...

最小実装例(ephemeral を CTE 的に利用)

-- models/stg/orders_ephemeral.sql
{{ config(materialized='ephemeral') }}
select
  o.order_id,
  o.customer_id,
  date_trunc('day', o.order_ts) as order_date
from {{ ref('raw_orders') }} as o;

-- models/stg/payments_ephemeral.sql
{{ config(materialized='ephemeral') }}
select
  p.order_id,
  sum(p.amount) as paid_amount
from {{ ref('raw_payments') }} as p
group by 1;

-- models/marts/fct_orders.sql
{{ config(materialized='table') }}
select
  o.order_id,
  o.customer_id,
  p.paid_amount
from {{ ref('orders_ephemeral') }} as o
left join {{ ref('payments_ephemeral') }} as p
  on o.order_id = p.order_id;

コンパイルと依存関係: 何がいつ実行されるか

dbt は DAG を解決し、参照される ephemeral モデルを参照側モデルの SQL にインライン化してから実行します。ephemeral 自体が単独でデータベースに対してクエリを発行することはありません。したがって、ephemeral モデル単体を dbt run で選択しても、永続オブジェクトは作成されず、実行すべきクエリも基本的に存在しません。

pre-hook/post-hook、grants、索引・クラスタリングなど、リレーション作成時に適用される機能は ephemeral には適用されません。テストは例外で、テスト用のクエリ内で ephemeral がインライン化されるため実行可能です。

  • dbt run -s 最終モデル を実行すると、依存する ephemeral は自動で埋め込まれる
  • ephemeral は単独実行しても何も作られない(インライン先がないため)
  • hooks / grants は適用不可。必要なら view/table を使う
  • incremental 設定や unique_key は ephemeral には無関係

コンパイルの確認と選択実行の例

# 依存関係ごとに最終モデルをコンパイル
$ dbt compile -s marts.fct_orders

# どのノードが対象になるかを確認
$ dbt ls -s marts.fct_orders --resource-type model

# 参考: コンパイル後の SQL(概念例)
with ep_orders as (
  select ... -- orders_ephemeral が展開
), ep_payments as (
  select ... -- payments_ephemeral が展開
)
select ... from ep_orders left join ep_payments on ...

性能・コスト設計の指針

ephemeral は中間結果を永続化しないため、ストレージや権限設定のオーバーヘッドがありません。一方で、参照側のクエリが肥大化しやすく、CTE の段数やクエリ長に制限があるエンジンでは失敗や最適化不足の原因になります。大きな結合・ウィンドウ関数・重い集計を多数の ephemeral に分割しても、結局は1本のクエリに合成される点に注意が必要です。

設計上の目安としては、1つの消費者(最終モデル)だけが使う小規模な整形には ephemeral、複数の消費者が再利用する共有変換には view、重くて毎回再計算したくない処理には table/incremental を選びます。デバッグ容易性が重要な段階や、エンジン側のクエリ長制約に近い場合は view 化を検討します。

  • 小さな変換・単一消費者 → ephemeral
  • 再利用・検証容易性重視 → view
  • 重計算の再実行回避 → table / incremental
  • クエリ長や CTE 段数の制約に注意。長大化したら分割・永続化を検討

階層別デフォルトの設定例(プロジェクト単位)

# dbt_project.yml(例)
models:
  my_project:
    staging:
      +materialized: ephemeral
    marts:
      +materialized: table

ベストプラクティスとアンチパターン

ephemeral は命名や場所で用途を明確にします。stg 配下で軽量整形を行い、marts 側で最終化する構造にすると、インライン化の境界がわかりやすくなります。複数箇所から再利用したい処理は積極的に view/table へ昇格させ、単一消費者に閉じる処理のみ ephemeral に保ちます。

アンチパターンは、重い処理を多数の ephemeral に細切れにしてしまい、結果として非常に長い1本のクエリを生成するケースです。また、5段以上の深いチェーンや複雑なウィンドウ関数の多用は、最適化が難しくなります。デバッグや権限付与、フックの適用が必要な場合も ephemeral ではなく他のマテリアライゼーションを選びましょう。

  • 用途で層分け(stg: ephemeral、marts: table/view)
  • 複数消費者がいる処理は view/table に昇格
  • 深いチェーンや重いウィンドウは避け、必要なら分割・永続化
  • hooks/grants が必要な場合は ephemeral を使わない

切り替えしやすいパターン(変数で制御)

-- dbt_project.yml(例)
vars:
  stg_materialization: 'ephemeral'

-- models/stg/_base.sql(各 stg モデルの先頭など)
{{ config(materialized=var('stg_materialization', 'ephemeral')) }}

-- デバッグ時は: stg_materialization を 'view' に変更してビルド

実装とデバッグ: コンパイル成果物の確認

ephemeral の効果を確認するには、コンパイル後の SQL を見るのが確実です。target/compiled 配下に生成される参照側モデルの SQL に、ephemeral モデルの SELECT が CTE として展開されます。これにより、本番実行時にどの程度のクエリになるか把握できます。

デバッグ時に中間結果を直接見たい場合は、一時的に view に切り替えます。ephemeral のままでもテストは実行可能ですが、行数が大きい場合や複雑なロジックでは、永続化して段階的に検証する方が安全です。

  • dbt compile で target/compiled を確認
  • 切り替え変数で ephemeral ⇄ view を素早く変更
  • 行数・複雑度が高い箇所は一時的に永続化して検証

コンパイル後のイメージとコマンド

# コンパイルのみ
$ dbt compile -s marts.fct_orders

# ビルド(モデル・テスト包括)
$ dbt build -s marts.fct_orders

-- コンパイル後の SQL(概念例)
with orders_ephemeral as (
  select ...
), payments_ephemeral as (
  select ...
)
select ... from orders_ephemeral o
left join payments_ephemeral p on o.order_id = p.order_id

試験対策まとめ(Analytics Engineer 向け)

試験では、ephemeral の定義(非永続・CTE としてインライン化)と、他マテリアライゼーションとの使い分けが頻出です。特に、ephemeral は単独で実行されないこと、hooks/grants が適用されないこと、重い処理や再利用には不向きであることを押さえてください。

また、参照側モデルを選択実行すれば ephemeral は自動的に含まれる点、テストクエリ内でもインライン化されて実行可能である点が問われることがあります。

  • キーワード: 非永続、CTE、インライン化、単独実行不可
  • 使い分け: 軽量・単一消費者 → ephemeral、再利用 → view、重い処理 → table/incremental
  • hooks/grants 不適用、テストではインライン化されて実行可

押さえておく CLI と設定

$ dbt run -s marts.fct_orders
# 参照される ephemeral は自動でインライン化

-- モデル先頭の設定例
{{ config(materialized='ephemeral') }}

問題で確認

Analytics Engineer

問題 1

2つの小規模なステージングモデルがあり、どちらも単一のファクトモデルからのみ参照されます。再利用予定はなく、重い集計もありません。最も適切なマテリアライゼーションはどれですか?

  1. A. 両方とも ephemeral
  2. B. 両方とも view
  3. C. 両方とも table
  4. D. 両方とも incremental

正解: A

単一の下流のみが利用し、軽量な変換であれば ephemeral で CTE としてインライン化するのが適切です。再利用や重い処理がある場合は view/table/incremental を検討します。

よくある質問

ephemeral モデルに対してテストは実行できますか?

はい。テスト用のクエリ内で当該モデルが CTE としてインライン化されるため、テストは実行可能です。大規模データでの重いテストは、必要に応じて一時的に view/table 化して検証することをおすすめします。

ephemeral はどのデータプラットフォームでも使えますか?

主要なアダプタでは CTE(または同等の仕組み)がサポートされており、ephemeral は一般的に利用できます。ただしエンジンごとのクエリ長や CTE 段数の制約、最適化特性は異なるため、長大なクエリになる場合は view/table への切り替えを検討してください。

hooks や grants を適用したい場合はどうすればよいですか?

ephemeral には pre/post-hook や grants は適用されません。これらが必要な場合は view/table(または incremental)を選択してください。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.