Проблема, которую решает dbt

Что было больно до dbt и какие именно практики он принёс в мир SQL-трансформаций.

SQL-хаос — состояние, когда логика трансформаций размазана по сотням несвязанных запросов без тестов, версий и документации, и никто не знает полной картины.

Как выглядела жизнь до dbt

Представьте компанию, где десять аналитиков пишут SQL. У каждого свой набор «сохранённых запросов» в редакторе. Метрика «выручка» считается в дашборде маркетинга одним способом, в отчёте финансов — другим, в выгрузке для совета директоров — третьим. Когда генеральный спрашивает «сколько мы заработали?», три отдела называют три разные цифры — и все формально правы, потому что определения разошлись.

Запросы запускались вручную или через хрупкие cron-скрипты. Если запрос B читал таблицу, которую создаёт запрос A, кто-то должен был помнить запустить A раньше B. Забыл — получил вчерашние данные или ошибку. Никто не тестировал результат: первичный ключ внезапно задвоился, и это всплывало через неделю в отчёте, когда уже поздно.

Четыре боли и четыре ответа dbt

БольЧто давал «голый SQL»Что даёт dbt
Нет версионированияЗапрос живёт в голове или в чатеКаждая модель — файл в git, история изменений, ревью
Нет тестовОшибку находит бизнес в отчётеТесты данных (unique, not_null, отношения) в коде
Нет документации«Спроси у Васи, он писал»Авто-документация и граф зависимостей
Нет порядка запускаПомни сам или пиши cronDAG строится автоматически по ref()

Как работает под капотом

Идея dbt обманчиво проста: вы по-прежнему пишете обычный SELECT, но dbt оборачивает его в инженерную обвязку. Из файла-модели dbt сам строит команду CREATE TABLE AS или CREATE VIEW AS, определяет порядок запуска по ссылкам между моделями, прогоняет тесты и собирает документацию. Вы пишете что посчитать, dbt берёт на себя как это выполнить надёжно.

-- Демонстрация SQL-хаоса: две версии "активного клиента"
CREATE TABLE orders (id INTEGER, customer_id INTEGER, days_since INTEGER);
INSERT INTO orders VALUES (1, 10, 5), (2, 10, 40), (3, 20, 80);

-- Отдел A: активный = заказ за 30 дней
SELECT DISTINCT customer_id FROM orders WHERE days_since <= 30;
-- Отдел B: активный = заказ за 60 дней
SELECT DISTINCT customer_id FROM orders WHERE days_since <= 60;

Два запроса дают разные ответы, потому что определение «активный» нигде не зафиксировано. dbt решает это так: определение пишется один раз в модели, и все ссылаются на неё.

Частые ошибки

  • Думать, что dbt — это новый язык запросов. Нет, это тот же SQL вашего хранилища плюс обвязка.
  • Ожидать, что dbt доставит данные. dbt не выгружает данные из источников — он только трансформирует то, что уже в хранилище (об этом — урок про ELT).
  • Внедрять dbt ради «модно», не имея боли. Если SQL-трансформаций мало и они стабильны, выгода будет меньше.

Итоги

  • До dbt логика трансформаций жила без версий, тестов, документации и порядка запуска.
  • dbt закрывает ровно эти четыре боли, оставаясь обычным SQL под капотом.
  • Ключевой эффект — единый источник определений и доверие к данным.
Проверьте себя
1. Какую из этих задач dbt НЕ решает?
AВерсионирование трансформаций
BТестирование данных
CДоставку (загрузку) сырых данных из источников в хранилище
DДокументирование моделей
2. Почему три отдела называли три разные цифры выручки?
AХранилище работало с ошибками
BОпределение метрики было продублировано в разных запросах и разошлось
CSQL не поддерживает агрегацию
DДанные приходили с задержкой