С редний уровень: Шаги трансформации, созданные для определенных целей
Как только наши атомы готовы к работе, мы приступим к их объединению в более сложные, связанные молекулярные формы. Средний уровень — это место, где живут эти молекулы, создавая разнообразные формы с конкретными целями на пути к более сложным белкам и клеткам, которые мы будем использовать для оживления наших продуктов данных.
Средний уровень: Файлы и папки
Давайте рассмотрим средний уровень нашего проекта, чтобы более конкретно понять цель этого этапа.
models/intermediate
└── finance
├── _int_finance__models.yml
└── int_payments_pivoted_to_orders.sql
- Папки
- ✅ Подкаталоги на основе бизнес-группировок. Подобно уровню подготовки, мы разместим этот уровень моделей внутри их собственной подкаталога
intermediate
. В отличие от уровня подготовки, здесь мы переходим к бизнес-конформности, разделяя наши модели на подкаталоги не по их исходной системе, а по их области бизнес-задач.
- ✅ Подкаталоги на основе бизнес-группировок. Подобно уровню подготовки, мы разместим этот уровень моделей внутри их собственной подкаталога
- Имена файлов
✅ int_[entity]s_[verb]s.sql
- разнообразие трансформаций, которые могут происходить на среднем уровне, делает сложным строгое определение их имен. Лучший принцип — думать о глаголах (например,pivoted
,aggregated_to_user
,joined
,fanned_out_by_quantity
,funnel_created
и т.д.) на среднем уровне. В нашем примере проекта мы используем промежуточную модель для поворота платежей к зерну заказа, поэтому называем нашу модельint_payments_pivoted_to_orders
. Это позволяет любому быстро понять, что происходит в этой модели, даже если они не знают SQL. Эта ясность стоит длинного имени файла. Важно отметить, что на этом уровне мы убрали двойные подчеркивания. Переходя к бизнес-конформным концепциям, нам больше не нужно разделять систему и сущность и просто ссылаться на объединенную сущность, если это возможно. В случаях, когда вам нужны промежуточные модели для работы на уровне исходной системы (например,int_shopify__orders_summed
,int_core__orders_summed
, которые вы позже объедините), вы сохраните двойные подчеркивания. Некоторые люди предпочитают также разделять сущность и глаголы двойными подчеркиваниями. Это вопрос предпочтений, но в нашем опыте часто существует внутренняя связь между сущностями и глаголами на этом уровне, что делает это трудным для поддержания.
Пример проекта очень прост для иллюстративных целей. Такой уровень разделения в наших пост-стейджинговых слоях, вероятно, не нужен при работе с таким небольшим количеством моделей. Помните, наша цель — единый источник правды. Мы не хотим, чтобы финансы и маркетинг работали с отдельными моделями orders
, мы хотим использовать наш проект dbt как средство для объединения этих определений! Поэтому не разделяйте и не оптимизируйте слишком рано. Если у вас меньше 10 моделей marts и нет проблем с их разработкой и использованием, можете полностью отказаться от подкаталогов (кроме уровня подготовки, где вы всегда должны их реализовывать, добавляя новые исходные системы в ваш проект), пока проект не вырастет до такой степени, что они действительно понадобятся. Использование dbt всегда связано с упрощением сложности.
Средний уровень: Модели
Ниже представлена единственная промежуточная модель из нашего небольшого примера проекта. Это отличный пример использования в соответствии с нашими принципами, служащий ясной единственной цели: группировка и поворот модели подготовки к другому зерну. Она использует немного Jinja, чтобы сделать модель более DRY (стремление к DRY применяется к коду, который мы пишем внутри одной модели, в дополнение к трансформациям по всему коду), но не пугайтесь, если вы еще не совсем уверены в Jinja. Глядя на имя CTE, pivot_and_aggregate_payments_to_order_grain
, мы получаем очень четкое представление о том, что происходит внутри этого блока. Описательно маркируя трансформации, происходящие внутри наших CTE в модели, так же как мы делаем это с нашими файлами и папками, даже заинтересованная сторона, не знающая SQL, сможет понять цель этого раздела, если не код. Когда вы начнете писать более сложные трансформации, выходя из уровня подготовки, держите эту идею в голове. Так же, как наши модели соединяются в DAG и рассказывают историю наших трансформаций в макромасштабе, CTE могут делать это в меньшем масштабе внутри наших файлов моделей.
-- int_payments_pivoted_to_orders.sql
{%- set payment_methods = ['bank_transfer','credit_card','coupon','gift_card'] -%}
with
payments as (
select * from {{ ref('stg_stripe__payments') }}
),
pivot_and_aggregate_payments_to_order_grain as (
select
order_id,
{% for payment_method in payment_methods -%}
sum(
case
when payment_method = '{{ payment_method }}' and
status = 'success'
then amount
else 0
end
) as {{ payment_method }}_amount,
{%- endfor %}
sum(case when status = 'success' then amount end) as total_amount
from payments
group by 1
)
select * from pivot_and_aggregate_payments_to_order_grain
- ❌ Доступны конечным пользователям. Промежуточные модели, как правило, не должны быть доступны в основной производственной схеме. Они не предназначены для вывода на конечные цели, такие как панели управления или приложения, поэтому лучше держать их отдельно от моделей, которые таковыми являются, чтобы вы могли легче контролировать управление данными и их обнаружение.
- ✅ Материализованы эфемерно. Учитывая вышеизложенное, одним из популярных вариантов является по умолчанию материализация промежуточных моделей эфемерно. Это, как правило, лучшее ме сто для начала с точки зрения простоты. Это позволит избежать ненужных моделей в вашем хранилище с минимальной конфигурацией. Однако имейте в виду, что простота эфемерных моделей несколько усложняет отладку, так как они интерполируются в модели, которые их
ref
, а не существуют сами по себе, чтобы вы могли просмотреть их вывод. - ✅ Материализованы как представления в пользовательской схеме с особыми разрешениями. Более надежным вариантом является материализация ваших промежуточных моделей как представлений в определенной пользовательской схеме, вне вашей основной производственной схемы. Это дает вам дополнительное понимание разработки и упрощает отладку по мере увеличения количества и сложности ваших моделей, оставаясь при этом легким в реализации и занимая незначительное пространство.
Существует три интерфейса к организационному графу знаний, который мы кодируем в dbt: DAG, структура файлов и папок нашего кода и вывод в хранилище. Поэтому очень важно, чтобы мы намеренно учитывали этот вывод! Думайте о схемах, таблицах и представлениях, которые мы создаем в хранилище, как о части UX, в дополнение к панелям управления, ML, приложениям и другим случаям использования, которые вы можете нацелить для данных. Обеспечение того, чтобы наш вывод был хорошо назван и сгруппирован, а модели, не предназначенные для широкого использования, либо не материализованы, либо построены в специальных областях с определенными разрешениями, имеет решающее значение для достижения этого.
-
Цели промежуточных моделей, поскольку они служат для разделения сложности наших моделей marts, могут принимать столько форм, сколько может потребовать трансформация данных. Некоторые из наиболее распространенных случаев использования промежуточных моделей включают:
- ✅ Структурное упрощение. Объединение разумного количества (обычно от 4 до 6) сущностей или концепций (моделей подготовки или, возможно, других промежуточных моделей), которые будут объединены с другой аналогично предназначенной промежуточной моделью для создания марта — вместо того, чтобы иметь 10 соединений в нашем марте, мы можем соединить две промежуточные модели, каждая из которых содержит часть сложности, что дает нам повышенную читаемость, гибкость, поверхность тестирования и понимание наших компонентов.
- ✅ Изменение зерна. Промежуточные модели часто используются для расширения или сжатия моделей до правильного составного зерна — если мы строим март для
order_items
, который требует от нас расширения нашихorders
на основе столбцаquantity
, создавая новую единую строку для каждого элемента, это было бы идеально сделать в конкретной промежуточной модели, чтобы сохранить ясность в нашем марте и легче увидеть, что наше зерно правильно, прежде чем мы смешаем его с другими комп онентами. - ✅ Изоляция сложных операций. Полезно перемещать любые особенно сложные или трудные для понимания части логики в их собственные промежуточные модели. Это не только упрощает их доработку и отладку, но и упрощает последующие модели, которые могут ссылаться на эту концепцию более четко читаемым образом. Например, в примере с расширением
quantity
, мы выигрываем, изолируя эту сложную часть логики, чтобы мы могли быстро отладить и тщательно протестировать эту трансформацию, а модели ниже по потоку могут ссылаться наorder_items
так, что это интуитивно легко понять.
Пока мы не дойдем до уровня marts и не начнем строить наши различные выводы, мы в идеале хотим, чтобы наш DAG выглядел как наконечник стрелы, направленный вправо. По мере того, как мы переходим от соответствия источнику к соответствию бизнесу, мы также переходим от многочисленных, узких, изолированных концепций к меньшему количеству, более широких, объединенных концепций. Мы объединяем наши компоненты в более широкие, более богатые концепции, и это создает эту форму в нашем DAG. Таким образом, когда мы дойдем до уровня marts, у нас будет надежный набор компонентов, которые можно быстро и легко настроить в любую конфигурацию, чтобы ответить на различные вопросы и удовлетворить конкретные потребности. Одно из правил, чтобы убедиться, что вы следуете этому шаблону на уровне отдельной модели, — это разрешать несколько входов в модель, но не несколько выходов. Несколько стрелок, входящих в наши пост-стейджинговые модели, — это здорово и ожидаемо, несколько стрелок, выходящих — это тревожный сигнал. Безусловно, есть ситуации, когда вам нужно нарушить это правило, но это то, о чем нужно знать, быть осторожным и избегать, когда это возможно.