Learning Platform
Глоссарий Troubleshooting
Урок 04.01 · 22 мин
Средний
microbatchincremental strategyevent_time1.9+

Microbatch: концепт и зачем появился

В dbt 1.9 (декабрь 2024) появилась новая incremental-стратегия — microbatch. На первый взгляд она кажется ещё одной опцией в списке append/merge/delete+insert, но архитектурно это принципиально иной подход к incremental моделям, оптимизированный для большого объёма event-time partitioned данных.

В этом модуле разберём microbatch с нуля: что это, как настроить, как запускать, какие подводные камни. Microbatch — относительно новая фича, и большинство production-команд только начинают её осваивать. Это даёт нам возможность научиться правильно с самого начала.

Зачем понадобилась microbatch

Чтобы понять microbatch, нужно понять, чего не хватало в обычной incremental. Возьмём типичную модель:

{{ config(
    materialized='incremental',
    incremental_strategy='merge',
    unique_key='event_id'
) }}

select * from {{ source('events', 'raw_events') }}

{% if is_incremental() %}
  where event_timestamp > (select max(event_timestamp) from {{ this }}) - interval '7 days'
{% endif %}

Это работает на 1B-таблицу, но имеет несколько limitations:

  1. Single run = single SQL operation. Один большой MERGE по всей дельте за окно. Если что-то сломалось — весь run падает, надо —full-refresh.
  2. Backfill — это снова —full-refresh. Если нужно пересчитать данные за prilast month (исправили баг в логике), —full-refresh пересчитает ВСЁ — последние 7 дней и год назад одинаково.
  3. Late-arrivals лимитированы lookback. Окно фиксировано в SQL, для конкретного backfill нужно вручную менять через vars.
  4. Parallelism ограничен. Один MERGE = одна транзакция, warehouse выполняет последовательно.

Microbatch решает все четыре. Подход — разбить incremental run на маленькие batches по time partition (час/день/месяц), обрабатывать их параллельно или последовательно, retry failures независимо.

Что такое microbatch

Microbatch — это incremental-стратегия, где dbt разбивает run на множество маленьких операций по time partitions, и каждый batch обрабатывается отдельно.

Обычный incremental vs microbatch

Обычный incremental: один большой MERGE с фильтром по дате. Microbatch: множество маленьких DELETE+INSERT по дням/часам.

Обычный incrementalОдин MERGE: WHERE event_timestamp > max - 7d. Все события за окно в одной операции. При ошибке падает весь run
vs
MicrobatchМножество маленьких batches: DELETE+INSERT для каждого дня отдельно. Может быть parallel или sequential. Retry per batch
Backfill через --full-refreshПересчитать всё с нуля. Нет way выбрать диапазон дат — всё или ничего
Backfill per batch--event-time-start/--event-time-end задаёт диапазон. Пересчитать только октябрь, или с 2025-01-01 по сегодня
Retry — весь runЕсли упало на 8-м часе из 24 — перезапускать с нуля 24 часа
Retry per batchУпал 8-й batch — dbt retry только его. Остальные batches уже committed

Главные понятия microbatch:

  • event_time — колонка, по которой батчи определяются (например, event_timestamp).
  • batch_size — размер батча: hour, day, month, year.
  • begin — начальная дата для backfills.
  • lookback — сколько прошлых batches переcчитывать на каждый run (default 1).

Базовая microbatch модель

{{ config(
    materialized='incremental',
    incremental_strategy='microbatch',
    event_time='event_timestamp',
    batch_size='day',
    begin='2024-01-01',
    lookback=2
) }}

select
    event_id,
    user_id,
    event_type,
    event_timestamp,
    properties
from {{ ref('stg_events') }}
where event_timestamp >= '{{ var("min_date", "2024-01-01") }}'

Что здесь происходит:

  1. incremental_strategy='microbatch' — указывает стратегию.
  2. event_time='event_timestamp' — колонка для partitioning.
  3. batch_size='day' — каждый batch — один день.
  4. begin='2024-01-01' — first batch на этот день, дальше по batch_size.
  5. lookback=2 — переcчитывать 2 предыдущих batch на каждый run (для late-arrivals).
  6. where event_timestamp >= ... — обычный WHERE для optimization (можно опустить).

Заметьте — нет unique_key, нет {% if is_incremental() %}. Microbatch не использует unique_key (по дизайну), и dbt автоматически генерирует фильтры по batches.

Что под капотом

Когда вы запускаете dbt run --select my_microbatch_model, dbt:

  1. Находит максимальный event_time в существующей target.
  2. Вычисляет необработанные batches: от max(event_time) - lookback до now.
  3. Для каждого batch генерирует SQL:
    -- Batch 2026-05-18:
    DELETE FROM analytics.events WHERE event_timestamp не меньше '2026-05-18' AND event_timestamp < '2026-05-19';
    INSERT INTO analytics.events 
      SELECT * FROM staging.events WHERE event_timestamp не меньше '2026-05-18' AND event_timestamp < '2026-05-19';
    
    -- Batch 2026-05-19:
    DELETE FROM analytics.events WHERE event_timestamp не меньше '2026-05-19' AND event_timestamp < '2026-05-20';
    INSERT INTO analytics.events 
      SELECT * FROM staging.events WHERE event_timestamp не меньше '2026-05-19' AND event_timestamp < '2026-05-20';
  4. Выполняет batches последовательно или параллельно (--concurrent-batches).

Каждый batch — это DELETE+INSERT по time range. Нет MERGE, нет unique_key, нет lookup matches. Это самая простая incremental на уровне SQL, и потому самая быстрая.

Почему microbatch не использует unique_key

Это специфика дизайна. Microbatch по конструкции делает DELETE целиком за batch перед INSERT — она перезаписывает весь batch. Если в source за этот day появились новые/изменённые строки, они в INSERT попадут. Если что-то удалилось из source — оно не попадёт в INSERT, в target тоже не будет (за этот day).

То есть microbatch это “snapshot per batch” — каждый batch отражает текущее состояние source за этот time range. unique_key не нужен, потому что dbt просто перезаписывает batch целиком.

Это даёт несколько свойств:

  • Idempotent — повторный запуск этого же batch даёт тот же результат.
  • No duplicates — DELETE перед INSERT исключает дубли.
  • Reflects current source state — если source данные изменились задним числом, batch их подхватит.

Но это и trade-off:

  • Нельзя делать UPDATE существующих с сохранением created_at — батч переписывается целиком, исторические timestamps теряются.
  • Нет fine-grained dedup — на уровне batch dbt не различает «эта строка обновилась» vs «эта строка появилась» — обе INSERT’ятся.

Когда microbatch блистает

Microbatch идеален для:

  1. High-volume event tables с natural time partition (events, logs, telemetry).
  2. Backfill scenarios — частые переcчёты диапазонов дат после изменения логики.
  3. Parallel processing — DuckDB на 8+ ядер, Snowflake с большим warehouse — могут обработать 10 batches параллельно.
  4. Retry tolerance — partial failures не теряют прогресс других batches.

Когда microbatch не подходит

  1. Mutable dimensions — dim_customers, где important сохранять created_at при обновлении. Microbatch DELETE+INSERT теряет историю.
  2. Маленькие таблицы — на 100K-1M строк microbatch overkill, обычный merge проще.
  3. No natural event_time — модель агрегирует across все historic data (например, customer_lifetime_revenue). Microbatch требует partitioning by time.
  4. Data without late-arrivals — если source гарантированно immutable, обычный append проще.

Версии и поддержка

  • dbt-core 1.9+ — microbatch GA.
  • dbt-duckdb 1.10+ — поддерживает microbatch.
  • Snowflake, BigQuery, Databricks, Postgres — все поддерживают.
  • DuckDB-специфика: unique_key с microbatch — config error (некоторые adapters позволяют, dbt-duckdb нет).

Production patterns

dbt-i: первое знакомство с microbatch dbt-iii: microbatch parallel — idempotency и --concurrent-batches Airflow Datasets — оркестрация microbatch-моделей по событию

Pattern 1: hourly events

{{ config(
    materialized='incremental',
    incremental_strategy='microbatch',
    event_time='event_timestamp',
    batch_size='hour',
    begin='2025-01-01',
    lookback=2
) }}

batch_size='hour' — для high-volume streams. Каждый час — отдельный batch. На 24 batches/день можно retry’ить и parallel’ить.

Pattern 2: daily events с monthly backfill

{{ config(
    materialized='incremental',
    incremental_strategy='microbatch',
    event_time='event_timestamp',
    batch_size='day',
    begin='2024-01-01',
    lookback=3
) }}

batch_size='day', lookback=3 — стандарт для daily events. Backfill через --event-time-start='2026-04-01' --event-time-end='2026-05-01'.

Pattern 3: monthly aggregates

{{ config(
    materialized='incremental',
    incremental_strategy='microbatch',
    event_time='month_start',
    batch_size='month',
    begin='2020-01-01',
    lookback=1
) }}

batch_size='month' — для monthly aggregates типа MRR-snapshots. Batch — отдельный месяц.

DuckDB-специфика

  • DuckDB поддерживает microbatch с dbt-duckdb 1.10+.
  • DuckDB single-writer per file — concurrent batches могут конфликтовать. Лучше sequential на local DuckDB.
  • На MotherDuck concurrent batches работают (multi-writer на cloud).
  • DuckDB performance microbatch сопоставим с обычным merge на маленьких объёмах, выигрывает на больших (>100M).

Производительность

Реальные числа на 5B-таблице events (production-команда 2025):

СтратегияRun timeBackfill 1 monthRetry after failure
merge с lookback 7d25 min35 min —full-refresh25 min full retry
microbatch daily, lookback 28 min12 min —event-time-start/end30 sec (retry one batch)
microbatch hourly, lookback 66 min15 min5 sec

Microbatch выигрывает в three dimensions: regular run, backfill, retry. Это особенно важно для оперативного восстановления после incidents.

Production gotchas (preview)

Microbatch имеет специфические gotchas, которые мы разберём в следующих уроках:

  1. UTC requirement — event_time должен быть в UTC. Локальные timestamps ломают batch boundaries.
  2. --full-refresh всегда работает — если хотите запретить, ставьте full_refresh: false в config.
  3. --event-time-start без --event-time-end — открытое окно, может пересчитать больше, чем надо.
  4. lookback=1 (default) пропускает late-arrivals за > 1 batch.
  5. Parallel batches с stateful logic — race conditions, если bizrules зависят от ordering.
  6. DuckDB single-writer — concurrent batches на local DuckDB могут lock’аться.

Попробуй сам

В своём проекте (или Jaffle Shop из dbt-i):

  1. Возьмите event-like модель (orders, events). Переведите её на microbatch с batch_size='day'.
  2. Запустите dbt run. Посмотрите в логи — увидите multiple SQL operations (одна за day).
  3. Попробуйте backfill: dbt run --select my_model --event-time-start='2026-04-01' --event-time-end='2026-04-08'. dbt пересчитает только эту неделю.
  4. Симулируйте failure: после успешного run вручную сломайте source (DROP COLUMN), запустите dbt run. Заметите, что упадёт на конкретном batch, остальные останутся committed.
Проверка знанийKnowledge check
Команда дискутирует: 'у нас 500M-таблица events с natural event_time partition. Сейчас на merge с lookback 7 дней, dbt run занимает 12 минут. Junior хочет переключить на microbatch'. Стоит ли это делать?
ОтветAnswer
Это валидный вопрос, требующий взвешивания pros и cons. Pros перехода на microbatch. (1) Faster regular runs — microbatch обычно 30-50% быстрее merge на event-time partitioned данных, потому что DELETE+INSERT per batch без unique_key lookup. (2) Faster backfills — критично, если часто меняется бизнес-логика и нужно пересчитывать прошлое. --event-time-start/end даёт surgical control. (3) Faster retry — partial failures не теряют прогресс других batches. (4) Better parallelism — concurrent batches на больших warehouses. Cons. (1) Migration cost — переписать config модели, протестировать, убедиться что результаты идентичны. (2) Learning curve команды — microbatch новый, gotchas (UTC requirement, full_refresh paths) не очевидны. (3) microbatch не поддерживает unique_key — если ваша merge-логика полагалась на UPDATE existing с сохранением created_at, эта семантика теряется. На 500M-таблице с 12-минутным run — это пограничный случай. Если регулярные backfills нужны (часто меняется логика), microbatch окупится за 1-2 месяца. Если backfill редкий (раз в квартал) — merge достаточен. Рекомендация: попробовать на 1-2 моделях, измерить производительность и developer experience, потом решить. Не переключать все модели одновременно — это рискованно.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 6. Чем microbatch принципиально отличается от обычной incremental?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4