ephemeral は、dbt のマテリアライゼーションの一種で、モデルをデータベースに永続化しません。参照先のモデル側の SQL に CTE として差し込まれるため、軽量な中間変換や一時的な整形によく適します。
この記事では、ephemeral の仕組み、他マテリアライゼーションとの違い、設計上の判断軸、実装・デバッグ方法、試験で問われやすいポイントをまとめます。内容は dbt の公式ドキュメントに沿った安定的な概念を前提にしています。
ephemeral は、ref で参照された側のモデルを、参照するモデルの SQL 内に CTE(またはサブクエリ相当)としてインライン化します。つまり、ephemeral 自体はデータベース上にテーブルやビューとしては作られません。ビジュアライゼーションツールや他システムから直接参照することはできず、あくまで参照する最終モデルの一部として実行されます。
軽量な整形・フィルタ・列追加などの中間処理で、かつ複数モデルから広く再利用しないケースに向いています。重い集計や広いテーブルを多数の下流から参照する場合は、view/table/incremental の方がメンテナンスや性能面で有利です。
| マテリアライゼーション | 永続性 | コンパイル結果 | 実行の単位 |
|---|---|---|---|
| ephemeral | 非永続 | 参照側 SQL の CTE へインライン | 参照モデルの1本のクエリ内で実行 |
| view | 永続(論理) | CREATE VIEW と SELECT | 各 SELECT 実行時に評価 |
| table | 永続(物理) | CREATE TABLE AS SELECT | dbt 実行時に作成・更新 |
| incremental | 永続(差分更新) | MERGE/INSERT による差分反映 | dbt 実行時に差分のみ更新 |
ephemeral の依存関係とインライン化イメージ
-- 参照側での実行時イメージ(概念)
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 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 化を検討します。
階層別デフォルトの設定例(プロジェクト単位)
# dbt_project.yml(例)
models:
my_project:
staging:
+materialized: ephemeral
marts:
+materialized: tableephemeral は命名や場所で用途を明確にします。stg 配下で軽量整形を行い、marts 側で最終化する構造にすると、インライン化の境界がわかりやすくなります。複数箇所から再利用したい処理は積極的に view/table へ昇格させ、単一消費者に閉じる処理のみ ephemeral に保ちます。
アンチパターンは、重い処理を多数の ephemeral に細切れにしてしまい、結果として非常に長い1本のクエリを生成するケースです。また、5段以上の深いチェーンや複雑なウィンドウ関数の多用は、最適化が難しくなります。デバッグや権限付与、フックの適用が必要な場合も 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 -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試験では、ephemeral の定義(非永続・CTE としてインライン化)と、他マテリアライゼーションとの使い分けが頻出です。特に、ephemeral は単独で実行されないこと、hooks/grants が適用されないこと、重い処理や再利用には不向きであることを押さえてください。
また、参照側モデルを選択実行すれば ephemeral は自動的に含まれる点、テストクエリ内でもインライン化されて実行可能である点が問われることがあります。
押さえておく CLI と設定
$ dbt run -s marts.fct_orders
# 参照される ephemeral は自動でインライン化
-- モデル先頭の設定例
{{ config(materialized='ephemeral') }}Analytics Engineer
問題 1
2つの小規模なステージングモデルがあり、どちらも単一のファクトモデルからのみ参照されます。再利用予定はなく、重い集計もありません。最も適切なマテリアライゼーションはどれですか?
正解: 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)を選択してください。
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)、設定優先度...