Первый запуск dbt на DuckDB
В прошлом уроке мы разобрали идею dbt на словах. Теперь сделаем это руками. К концу урока у вас будет работающий dbt-проект на DuckDB и первая таблица, созданная одной командой dbt run. Никакого облака, никаких оплат, всё локально на вашем ноутбуке.
Вам понадобится: установленный Python 3.10 или новее и терминал (командная строка). Терминалом, файлами и путями мы уже владеем со Ступени 0. А вот пара новых команд для подготовки окружения Python (venv, source ... activate, pip) на Ступени 0 ещё не встречалась — поэтому объясняем их прямо здесь, при первом использовании, с нуля.
Не торопитесь. Выполняйте команды по одной и сверяйте вывод с тем, что показано в уроке. Если вывод отличается — остановитесь и прочитайте сообщение об ошибке, оно почти всегда подсказывает причину.
Шаг 1. Установка dbt с адаптером DuckDB
dbt сам по себе не знает, как разговаривать с конкретным хранилищем. Для каждого хранилища есть свой “адаптер” — переходник. Нам нужен адаптер для DuckDB, он называется dbt-duckdb. Когда вы ставите dbt-duckdb, вместе с ним автоматически ставится и сам движок dbt, и DuckDB. Одной командой получаем всё.
Сначала создадим отдельную папку и виртуальное окружение Python (чтобы не засорять систему), затем поставим пакет:
mkdir dbt-first
cd dbt-first
python3 -m venv venv
source venv/bin/activate
pip install dbt-duckdb
Здесь четыре новые для вас команды. Разберём их по одной, без спешки — это базовый ритуал любого Python-проекта, его вы будете повторять всю карьеру:
mkdir dbt-firstиcd dbt-first— знакомо со Ступени 0: создаём папку под проект и заходим в неё.python3 -m venv venv— создаёт— изолированную песочницу для библиотек именно этого проекта. Появляется папкавиртуальное окружениеvenv/: внутри неё живёт отдельная копия Python и все пакеты, которые мы поставим. Так dbt в одном проекте и какая-нибудь другая библиотека в другом не конфликтуют по версиям.source venv/bin/activate—эту песочницу в текущем окне терминала. После неё командывключаетpythonиpipначинают работать внутриvenv, а не с системным Python. Признак, что всё получилось, — приставка(venv)в начале строки терминала. Песочница активна только в этом окне: откроете новое — активируйте заново.pip install dbt-duckdb—pipэто. Командойштатный установщик пакетов Pythonpip installон скачивает библиотекуdbt-duckdb(и заодно сам движок dbt и DuckDB) и кладёт её в нашу песочницуvenv.
ВНИМАНИЕ: на Windows строка активации другая. В WSL2/Linux/Mac — source venv/bin/activate (как выше). В обычном Windows PowerShell — venv\Scripts\Activate.ps1. Если идёте по DE-пути через WSL2 (рекомендуем), используйте вариант со source — он одинаковый для Linux и Mac.
После установки проверим, что dbt на месте:
dbt --version
Ожидаемый вывод (номера версий у вас могут немного отличаться):
Core:
- installed: 1.10.0
Plugins:
- duckdb: 1.10.0
Если вы видите версию Core и плагин duckdb — установка прошла успешно. Если команда dbt не находится, убедитесь, что виртуальное окружение активировано (строка source venv/bin/activate выше).
Шаг 2. Создание проекта командой dbt init
Теперь создадим сам проект. Команда dbt init задаст пару вопросов и разложит стартовые файлы:
dbt init jaffle
dbt спросит, какой адаптер использовать. Выберите duckdb (если предложит выбор из номеров — введите номер напротив duckdb). После этого dbt создаст папку jaffle/ с минимальным проектом. Ожидаемый вывод примерно такой:
Running with dbt=1.10.0
Your new dbt project "jaffle" was created!
dbt также попробует записать “профиль” — настройку подключения к хранилищу. Профиль хранится отдельно от проекта, в файле ~/.dbt/profiles.yml. Чтобы не зависеть от того, что именно записал init, мы зададим профиль явно сами — это надёжнее и понятнее для новичка.
Зайдём в папку проекта:
cd jaffle
Шаг 3. Минимальная настройка подключения
dbt-проекту нужно знать две вещи: как называется проект и куда (в какое хранилище) складывать таблицы. Первое уже задано в файле dbt_project.yml (его создал init). Второе — в профиле.
Создайте файл profiles.yml внутри папки проекта jaffle/ со следующим содержимым. Для DuckDB “хранилище” — это просто один файл на диске:
jaffle:
target: dev
outputs:
dev:
type: duckdb
path: jaffle.duckdb
Разберём по строкам без спешки:
jaffle— имя профиля, должно совпадать с тем, что указано вdbt_project.ymlв полеprofile.target: dev— какое окружение использовать по умолчанию (у нас одно —dev).type: duckdb— какой адаптер (наш переходник к DuckDB).path: jaffle.duckdb— имя файла, в котором DuckDB будет хранить данные. Его создаст dbt при первом запуске.
Чтобы dbt искал профиль именно в папке проекта, запускайте команды с флагом --profiles-dir . (точка — это “текущая папка”). Проверим, что dbt видит подключение:
dbt debug --profiles-dir .
Ожидаемый вывод (важна последняя строка):
Connection test: [OK connection ok]
All checks passed!
Если видите All checks passed! — подключение к DuckDB работает.
Шаг 4. Самая первая модель
dbt init уже положил пару примеров моделей в папку models/example/. Чтобы ничего не отвлекало, удалим их и создадим одну свою:
rm -rf models/example
mkdir models/example
Создайте файл models/example/my_first_model.sql с одним простым SELECT. Заметьте: никаких CREATE TABLE, только сам запрос — остальное допишет dbt:
SELECT
1 AS order_id,
'completed' AS status,
100 AS amount
UNION ALL
SELECT 2, 'cancelled', 50
UNION ALL
SELECT 3, 'completed', 75
Это игрушечные данные: три заказа прямо в запросе, без внешних таблиц. Так мы убираем из картины загрузку данных и фокусируемся только на том, как dbt превращает SELECT в таблицу.
Шаг 5. Команда dbt run — первый успех
Запускаем главную команду курса:
dbt run --profiles-dir .
Ожидаемый вывод:
Running with dbt=1.10.0
Found 1 model, 0 tests, 0 sources
Concurrency: 1 threads
1 of 1 START sql view model main.my_first_model ......... [RUN]
1 of 1 OK created sql view model main.my_first_model .... [OK in 0.05s]
Finished running 1 view model in 0.20s.
Completed successfully
Done. PASS=1 WARN=0 ERROR=0 SKIP=0 TOTAL=1
Главная строка — последняя: PASS=1 ... ERROR=0. Это значит, что dbt успешно создал из вашей модели объект в хранилище. Поздравляем: вы запустили dbt.
В выводе вы видите слово view, а не table. По умолчанию dbt создаёт представление (view) — это “виртуальная таблица”, сохранённый запрос. Почему так и как сделать настоящую таблицу — разберём в следующем уроке и подробно в модуле про материализации. Сейчас важно одно: dbt взял ваш SELECT и создал из него объект в хранилище.
Шаг 6. Проверим, что объект действительно создан
Откроем DuckDB и посмотрим, что внутри нашего файла-хранилища. dbt умеет выполнить произвольный запрос командой dbt show:
dbt show --profiles-dir . --inline "SELECT * FROM my_first_model"
Ожидаемый вывод:
| order_id | status | amount |
| -------- | --------- | ------ |
| 1 | completed | 100 |
| 2 | cancelled | 50 |
| 3 | completed | 75 |
Видите три строки? Значит, ваш SELECT действительно превратился в объект, который теперь можно запрашивать по имени my_first_model. Имя файла модели стало именем объекта в хранилище — ровно как мы обещали в прошлом уроке.
Что делать, если что-то пошло не так
command not found: dbt— не активировано виртуальное окружение. Выполнитеsource venv/bin/activateиз папкиdbt-first.Could not find profile named 'jaffle'— забыли флаг--profiles-dir .илиprofiles.ymlлежит не в той папке. Файл должен быть внутриjaffle/.Compilation Errorв SQL — опечатка в запросе модели. Прочитайте имя файла в сообщении и проверьте синтаксисSELECT.- Команда зависла или просит логин в облако — вы случайно запустили команду dbt Cloud. Нам нужен только локальный
dbt run, никакого облака.
Попробуй сам
- Добавьте в
my_first_model.sqlчетвёртый заказ: ещё один блокUNION ALL SELECT 4, 'completed', 200. Сохраните файл и снова выполнитеdbt run --profiles-dir .. Затем повторитеdbt show— убедитесь, что строк стало четыре. Вы только что изменили модель и пересобрали её одной командой. - Создайте вторую модель
models/example/completed_orders.sqlс запросом, который читает из первой:
SELECT order_id, amount
FROM my_first_model
WHERE status = 'completed'
Снова dbt run --profiles-dir . — теперь в выводе будет PASS=2. Вы создали две связанные модели. (Пока мы ссылаемся на первую модель по прямому имени; в следующих модулях вы узнаете про специальную функцию ref(), которая делает это правильно и автоматически выстраивает порядок.)