В чём отличие dbt от хранимых процедур?

«В чём отличие dbt от хранимых процедур?» — вопрос из категории ETL и пайплайны данных, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

dbt (Data Build Tool) и хранимые процедуры — это два принципиально разных подхода к трансформации данных в хранилище (DWH).

Аспект dbt (ELT-подход) Хранимые процедуры (ETL-подход)
Логика и версионирование Код (SQL + Jinja) хранится в Git. Легкое отслеживание изменений, code review, CI/CD. Код живет внутри БД. Версионирование и совместная разработка сложнее.
Модульность и зависимости Четкая модульность через ref('model_name'). dbt сам строит DAG зависимостей. Зависимости между процедурами часто неявные, требуют ручного управления.
Тестирование и документация Встроенные возможности: тесты на уникальность, not_null, свежесть данных. Автогенерация документации. Тестирование нужно организовывать вручную (отдельные скрипты, юнит-тесты).
Выполнение dbt генерирует и выполняет обычный SQL (CREATE TABLE AS SELECT ...). Прозрачно для оптимизатора БД. Выполняется процедурный код на SQL/PLpgSQL внутри БД. Может быть «черным ящиком».
Интеграция с оркестратором Идеально стыкуется с Airflow, Dagster (запуск dbt run как отдельной задачи). Оркестратор вызывает процедуру через CALL. Логика выполнения скрыта внутри БД.

Пример dbt-модели:

-- models/fct_orders.sql
{{ config(materialized='incremental') }}

SELECT
    o.order_id,
    o.customer_id,
    o.amount,
    c.customer_segment
FROM {{ ref('stg_orders') }} o
LEFT JOIN {{ ref('dim_customers') }} c USING (customer_id)
WHERE o.status = 'completed'
{% if is_incremental() %}
    AND o.order_date > (SELECT MAX(order_date) FROM {{ this }})
{% endif %}

В моей практике dbt обеспечивает лучшую управляемость, тестируемость и прозрачность пайплайнов данных для команды.