dbt exposures на собеседовании Data Engineer
EXPLAIN, чтобы понять, откуда берутся строки и где тратятся ресурсы запроса?Содержание:
Зачем нужны exposures
Exposure в dbt — это декларация внешнего потребителя ваших моделей: дашборда, ML-модели или приложения, которое читает данные из витрины. Проблема, которую он решает, простая: обычный dbt-граф обрывается на последней модели, и по нему не видно, что происходит с данными дальше. Когда аналитик спрашивает «а что сломается, если я перепишу fct_orders?» — без exposures ответа нет, потому что dbt не знает про дашборды и отчёты за пределами проекта.
Exposure не материализуется в базе — это чисто метаданные. Но в dbt docs и в графе lineage он появляется как финальный узел, замыкающий цепочку «источник → staging → витрина → потребитель».
# models/exposures.yml
exposures:
- name: weekly_revenue_dashboard
type: dashboard
maturity: high
url: https://datalens.yandex.ru/...
owner:
name: Marketing Team
email: marketing@company.ru
depends_on:
- ref('fct_orders')
- ref('dim_customers')На собесе DE это спрашивают в контексте data quality и владения данными: интервьюер проверяет, понимаете ли вы, как довести lineage до реального потребителя и как заранее понять, кого затронет ваше изменение.
Как описать exposure
Exposure объявляется в YAML и описывает потребителя набором полей. Ключевые из них:
name— уникальное имя потребителя, по нему exposure выбирается в командах dbt.type— категория потребителя. Допустимые значения:dashboard,notebook,analysis,ml,application. Влияет на иконку и группировку в docs.owner— имя и email ответственной команды. Именно к нему обращаются, когда модель ниже по потоку ломается.depends_on— список моделей и источников черезref()иsource(), от которых зависит потребитель. Это и есть связь, по которой строится lineage.urlиdescription— ссылка на сам дашборд и пояснение, чтобы человек в docs понял, что это и зачем.maturity— необязательный признак зрелости (high/medium/low), помогает отделить продовые дашборды от экспериментов.
Польза для lineage
Главная ценность exposures — impact-анализ. В сгенерированной документации (dbt docs generate) потребитель виден как финальная нода графа, и от любой модели можно проследить, какие дашборды и ML-модели её используют.
fct_orders (model)
└─ exposed by: weekly_revenue_dashboard (Marketing Team)Практический смысл: перед тем как менять схему или логику fct_orders, инженер видит, что от неё зависит дашборд маркетинга, и знает, кого предупредить о breaking change. Без exposures это знание живёт только в головах и всплывает уже после того, как у кого-то сломался отчёт.
Применение в CI
В CI exposures используют, чтобы прогонять проверки в границах реальных потребителей, а не по всему проекту подряд. dbt умеет выбирать по exposure через синтаксис селекторов:
# посмотреть, что стоит за конкретным дашбордом
dbt ls --select +exposure:weekly_revenue_dashboard
# пересобрать и протестировать всё, от чего зависит дашборд
dbt build --select +exposure:weekly_revenue_dashboardОператор + перед селектором подтягивает все апстрим-модели потребителя. В связке со Slim CI (сборка только изменённого через state:modified) это даёт точечную проверку: если PR трогает модель, от которой зависит продовый дашборд, пайплайн прогонит именно эту ветку графа и упадёт до мержа, если что-то не проходит тесты. Так breaking change отлавливается на этапе ревью, а не в проде.
Частые ошибки
Считать, что exposures создаются сами. dbt их не генерирует автоматически — их пишут и поддерживают руками. Если о новом дашборде забыли, в lineage его не будет, и impact-анализ соврёт.
Оставлять exposures протухшими. Дашборд удалили, а exposure остался — граф показывает несуществующего потребителя. Их нужно ревьюить вместе с моделями.
Путать exposure с моделью. Exposure ничего не материализует в БД и не выполняет SQL. Это метаданные о потребителе, а не таблица.
Не заполнять owner. Без владельца теряется главный смысл — некого предупредить при изменении. Exposure без контакта ответственного почти бесполезен.
Связанные темы
- dbt на собесе DE
- dbt incremental models для DE
- dbt sources и macros для DE
- Data lineage для DE
- Подготовка к собесу Data Engineer
FAQ
Чем exposure отличается от source и модели?
source описывает входные данные на входе в проект, модель — трансформацию внутри, а exposure — потребителя на выходе. Все три участвуют в lineage, но source и модели материализуются или читаются из БД, а exposure — только метаданные, замыкающие граф на дашборде или ML-модели.
Как понять, какие дашборды сломает изменение модели?
Через селектор dbt ls --select model_name+ можно вывести всё, что стоит ниже по потоку, включая exposures-потребителей. В CI это же используют, чтобы прогнать тесты именно по затронутой ветке. Именно ради такого impact-анализа exposures и заводят.
Проверяет ли dbt, что дашборд действительно работает?
Нет. dbt не ходит в BI-инструмент и не знает, жив ли дашборд. Exposure лишь фиксирует зависимость и владельца. Проверять «живость» самого дашборда — задача BI-платформы или отдельного мониторинга; dbt отвечает только за данные под ним.
Что писать в поле type для ML-модели?
Тип ml. Он подходит, когда витрину читает обучающий пайплайн или сервис инференса. Это помогает в docs отделить ML-потребителей от обычных дашбордов и понимать, что за изменением данных стоит переобучение модели, а не просто пересбор отчёта.
Это официальная информация?
Нет. Статья основана на документации dbt (версии 1.7+) и типовых практиках. Конкретные требования зависят от компании и уровня позиции.
Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.