Materializations decide how dbt saves your data models. They help you choose if data is saved as a table, a view, or handled differently for faster or flexible use.
Materializations (view, table, incremental, ephemeral) in dbt
Start learning this pattern below
Jump into concepts and practice - no test required
materialized: [view|table|incremental|ephemeral]
Specify materialization in the model's config block or in the dbt_project.yml file.
Each materialization affects performance and storage differently.
config(materialized='table')config(materialized='view')config(materialized='incremental')config(materialized='ephemeral')This example shows how to set each materialization type in dbt models. The incremental model updates only new data. The ephemeral model is used inside another model without creating a table or view.
/* Example dbt model using different materializations */ -- models/my_table_model.sql {{ config(materialized='table') }} select id, name from source_data -- models/my_view_model.sql {{ config(materialized='view') }} select id, name from source_data -- models/my_incremental_model.sql {{ config(materialized='incremental', unique_key='id') }} select id, name from source_data {% if is_incremental() %} where updated_at > (select max(updated_at) from {{ this }}) {% endif %} -- models/my_ephemeral_model.sql {{ config(materialized='ephemeral') }} select id, name from source_data where active = true -- models/using_ephemeral.sql select * from {{ ref('my_ephemeral_model') }}
Incremental models need a unique key to identify new or changed rows.
Ephemeral models are useful for reusable SQL snippets without extra storage.
Views always show the latest data but can be slower than tables for big data.
Materializations control how dbt saves or uses your data models.
Choose 'table' for permanent storage, 'view' for fresh queries, 'incremental' for efficient updates, and 'ephemeral' for inline SQL.
Each type helps balance speed, storage, and freshness based on your needs.
Practice
Solution
Step 1: Understand the purpose of 'table' materialization
The 'table' materialization creates a physical table in the database that stores data permanently.Step 2: Compare with other materializations
'view' creates a virtual table, 'incremental' updates existing tables efficiently, and 'ephemeral' runs inline SQL without creating tables.Final Answer:
table -> Option AQuick Check:
Permanent storage = table [OK]
- Confusing 'view' with 'table' as both represent data
- Thinking 'incremental' creates a full new table every time
- Assuming 'ephemeral' creates physical tables
Solution
Step 1: Recall dbt config syntax for materialization
dbt uses config() with the keyword 'materialized' to set materialization type.Step 2: Identify the correct keyword and format
The correct syntax is config(materialized = 'incremental'). Other options use wrong keywords or syntax.Final Answer:
config(materialized = 'incremental') -> Option BQuick Check:
Correct keyword is 'materialized' inside config() [OK]
- Using 'materialization' instead of 'materialized'
- Trying to call materialized as a function
- Using SQL-like SET syntax instead of config()
-- model.sql
{{ config(materialized='incremental', unique_key='id') }}
select id, value from source_table
{% if is_incremental() %}
where updated_at > (select max(updated_at) from {{ this }})
{% endif %}What happens when you run this model multiple times?
Solution
Step 1: Understand incremental materialization with unique_key
The model uses incremental materialization with a unique key 'id' to update data efficiently.Step 2: Analyze the is_incremental() condition
When running incrementally, it filters rows where 'updated_at' is newer than the max in the existing table, appending only new or updated rows.Final Answer:
The model appends only new or updated rows based on 'updated_at' -> Option CQuick Check:
Incremental + filter = append updates [OK]
- Thinking incremental rebuilds full table every run
- Confusing view materialization with incremental
- Ignoring the is_incremental() condition
{{ config(materialized='ephemeral') }}
select * from source_tableBut when you run dbt, you get an error saying the model is not found. What is the likely cause?
Solution
Step 1: Recall what ephemeral materialization does
Ephemeral models do not create tables or views; their SQL is inlined into dependent models.Step 2: Understand why the error occurs
Since ephemeral models don't create database objects, running them directly causes a 'model not found' error.Final Answer:
Ephemeral models do not create tables or views, so they cannot be run directly -> Option AQuick Check:
Ephemeral = inline SQL, no table/view created [OK]
- Trying to run ephemeral models directly
- Assuming ephemeral needs unique_key
- Confusing ephemeral with incremental
- Stores data permanently
- Updates only new rows efficiently
- Avoids rebuilding the entire dataset each run
Which materialization should you choose and why?
Solution
Step 1: Identify permanent storage requirement
Both 'table' and 'incremental' materializations store data permanently.Step 2: Consider update efficiency
'Table' rebuilds fully each run, while 'incremental' updates only new or changed rows efficiently.Step 3: Match requirements
Since you want to avoid full rebuilds and update only new rows, 'incremental' fits best.Final Answer:
Use 'incremental' materialization because it stores data permanently and updates only new rows -> Option DQuick Check:
Permanent + efficient updates = incremental [OK]
- Choosing 'table' and expecting incremental updates
- Picking 'view' which does not store data permanently
- Confusing ephemeral with storage options
