Table vs View vs Incremental in dbt: Key Differences and Usage
table stores data physically and rebuilds fully on each run, a view is a saved query that runs on demand without storing data, and an incremental model updates only new or changed data to improve performance and reduce processing time.Quick Comparison
This table summarizes the main differences between table, view, and incremental models in dbt.
| Feature | Table | View | Incremental |
|---|---|---|---|
| Data Storage | Physical storage of data | No storage, runs query on demand | Physical storage with partial updates |
| Performance | Slower on rebuilds due to full refresh | Fast for small queries, slower on complex queries | Faster by processing only new/changed data |
| Update Method | Full rebuild every run | Always fresh, no rebuild needed | Append or update only changed rows |
| Use Case | Stable datasets, large data | Lightweight, simple transformations | Large datasets with frequent updates |
| Cost | Higher storage and compute cost | Lower storage cost, compute cost on query | Balanced storage and compute cost |
Key Differences
Tables in dbt physically store the results of your SQL queries in the database. Each time you run dbt, the table is fully rebuilt, which can be slow for large datasets but ensures data is fully refreshed.
Views do not store data physically; instead, they save the SQL query itself. When you query a view, the database runs the query live. This means views are always up-to-date but can be slower for complex or large data because the query runs every time.
Incremental models combine the benefits of tables and views by storing data physically but only updating new or changed rows during dbt runs. This approach reduces processing time and cost for large datasets that update frequently, making it efficient for incremental data loads.
Code Comparison
Here is how you define a simple full-refresh table model in dbt that selects all data from a source.
{{ config(materialized='table') }}
select * from {{ source('my_source', 'my_table') }}Incremental Equivalent
This is the equivalent incremental model that only adds new rows based on a unique key and timestamp.
{{ config(materialized='incremental', unique_key='id') }}
select * from {{ source('my_source', 'my_table') }}
{% if is_incremental() %}
where updated_at > (select max(updated_at) from {{ this }})
{% endif %}When to Use Which
Choose table when you need a stable dataset that is fully rebuilt regularly and data freshness is critical without complex update logic.
Choose view for lightweight transformations or when you want always up-to-date data without storage cost, especially for small or simple datasets.
Choose incremental for large datasets that update frequently where full rebuilds are costly, and you want to optimize performance by processing only new or changed data.