Материализации: view, table, ephemeral
Одна и та же модель может стать представлением, таблицей или вообще раствориться в SQL — это выбор материализации.
Материализация — стратегия, по которой dbt физически воплощает модель в хранилище: как представление (view), как таблицу (table) или как встраиваемый подзапрос (ephemeral).
Зачем выбор
Модель — это SELECT, но воплотить его можно по-разному, и выбор влияет на скорость запросов и стоимость хранения. dbt даёт три базовые стратегии плюс инкрементальную (следующий урок).
view — представление
По умолчанию модель становится view: в хранилище хранится только сам запрос, а данные считаются заново при каждом обращении. Плюс — мгновенное «обновление» (всегда свежо) и ноль места под данные. Минус — медленно, если запрос тяжёлый и к нему часто обращаются.
table — таблица
Материализация table при каждом dbt run физически пересчитывает результат и сохраняет как таблицу. Плюс — быстрые последующие чтения (данные уже посчитаны). Минус — занимает место и устаревает между запусками dbt.
-- models/marts/daily_revenue.sql
{{ config(materialized='table') }}
select order_date, sum(amount) as revenue
from {{ ref('orders') }}
group by order_date
ephemeral — без объекта в хранилище
Материализация ephemeral вообще не создаёт объект. Вместо этого dbt подставляет тело модели как CTE прямо в те модели, которые на неё ссылаются. Плюс — не засоряет хранилище промежуточными объектами. Минус — на неё нельзя сослаться в BI, и её не видно как отдельный объект.
Когда что выбирать
| Материализация | Хранит данные | Когда выбрать |
| view | Нет (только запрос) | Лёгкие модели, staging, всегда нужна свежесть |
| table | Да | Тяжёлые витрины, к которым часто обращаются (BI) |
| ephemeral | Нет (CTE-вставка) | Промежуточная логика, переиспользуемая внутри других моделей |
| incremental | Да, дописывает | Очень большие таблицы (следующий урок) |
Как работает под капотом
Материализация — это шаблон, по которому dbt генерирует DDL. Для view это create view ... as (select ...); для table — create table ... as (select ...) с предварительным дропом старой; для ephemeral dbt не шлёт DDL вовсе, а вшивает запрос как with __dbt__cte__model as (...) в потребителя. Задают материализацию через {{ config(materialized='...') }} в самой модели или скопом по папке в dbt_project.yml.
Частые ошибки
- Делать table из всего подряд. Лёгкие staging-модели дешевле держать как view.
- Делать view из тяжёлой витрины для BI. Каждый дашборд будет пересчитывать запрос — лучше table.
- Ожидать, что на ephemeral можно сослаться извне. Её нет в хранилище как объекта.
Итоги
- view хранит только запрос (свежо, но медленно), table хранит данные (быстро, но место и устаревание).
- ephemeral встраивается как CTE и не создаёт объект — для промежуточной логики.
- Материализацию задают через
config(materialized=...)в модели или по папке в dbt_project.yml.