lag_tolerance
- YAML-файл проекта
- YAML-файл свойств
- Конфигурация в SQL-файле
models:
<resource-path>:
+state:
lag_tolerance: <duration_string>
models:
- name: my_model
config:
state:
lag_tolerance: <duration_string>
{{ config(
state={
"lag_tolerance": "<duration_string>"
}
) }}
Определение
Исходные системы могут обновляться чаще, чем требуется пересобирать некоторые нижестоящие модели. Например, модель для ежедневной отчётности не нужно обновлять чаще одного раза в день, даже если новые вышестоящие данные поступают каждый час, тогда как модель для расчёта метрик, доступных клиентам, использующая часть тех же источников, может требовать обновления каждые 30 минут.
lag_tolerance задаёт время, которое dbt State выжидает перед пересборкой узла при изменении вышестоящих данных. Узел пересобирается, только когда выполняются оба условия: с момента его последней сборки прошло больше времени, чем задано в lag_tolerance, и вышестоящие данные изменились с момента этой сборки. Это создаёт буфер, позволяющий экономить вычислительные ресурсы и соблюдать соглашения об уровне обслуживания (SLA) в отношении актуальности данных без ненужных пересборок. Поддерживаются два основных сценария:
- Согласование сборок с требованиями SLA:
lag_toleranceпозволяет напрямую согласовать выполнение моделей с требованиями SLA к актуальности данных, отделяя частые изменения вышестоящих данных от нижестоящих моделей с менее строгими требованиями к актуальности. - Экономия вычислительных ресурсов при нарушениях SLA вышестоящих зависимостей:
lag_toleranceзащищает ваш бюджет на вычисления при нарушениях SLA по актуальности, предотвращая затратные пересборки нижестоящих моделей на неизменившихся данных, когда вышестоящая зависимость не соответствует своему SLA по актуальности.
Конфигурация lag_tolerance принимает два типа значений:
-
Строки длительности в формате
<number><unit>:Единица измерения Допустимые значения Секунды s,second,secondsМинуты m,minute,minutesЧасы h,hour,hoursДни d,day,daysНедели w,week,weeks -
Выражения Jinja —
lag_toleranceвычисляется как шаблон Jinja, поэтому для динамического задания допустимых задержек можно использовать любые переменные контекста dbt (target,var(),env_var()). Это удобно для задания разных допустимых задержек в разных окружениях без дублирования блоков конфигурации:lag_tolerance: "{{ '4h' if target.name == 'prod' else '7d' }}"
Когда узел пересобирается
dbt State пересобирает узел, только когда выполняются оба условия. Если хотя бы одно из них не выполняется, используется существующий узел:
| Условие | Что оно означает |
|---|---|
| Допустимая задержка истекла | С момента последней сборки узла прошло больше времени, чем задано в его lag_tolerance. |
| Вышестоящие данные изменились | Хотя бы в одной вышестоящей зависимости появились новые данные с момента этой сборки. |
lag_tolerance задаёт минимальный интервал между пересборкамиlag_tolerance определяет, как часто узел может пересобираться, а не то, насколько актуальными должны быть его вышестоящие данные.
Пример
Допустим, у вас есть задание, которое запускается каждые 30 минут, для модели задана допустимая задержка 45m, а последняя сборка состоялась в 08:00. Новые вышестоящие данные поступили в 08:20.
| Запуск задания | Время с последней сборки | Есть новые вышестоящие данные с момента последней сборки? | Результат |
|---|---|---|---|
08:30 | 30m | Да | Повторное использование: допустимая задержка ещё не истекла. |
09:00 | 60m | Да | Пересборка: оба условия выполнены. |
09:30 | 30m | Нет | Повторное использование: допустимая задержка ещё не истекла, а вышестоящие данные не изменились. |
10:00 | 60m | Нет | Повторное использование: вышестоящие данные не изменились с 09:00. |
Данные, поступившие в 08:20, ожидали обработки до 09:00. Это был первый запуск, при котором с момента сборки прошло больше 45m и вышестоящие данные изменились. В 10:00 с момента сборки прошло достаточно времени, но, поскольку после 09:00 новые вышестоящие данные не поступали, dbt повторно использовал узел.
Чтобы пересобирать узел при каждом изменении его вышестоящих данных, установите lag_tolerance в 0s:
state:
lag_tolerance: 0s
Когда применяется lag_tolerance
lag_tolerance применяется только к проверкам актуальности данных. Нижестоящая модель всё равно пересобирается до истечения допустимой задержки, если скомпилированный SQL вышестоящей модели изменился с момента последнего запуска, независимо от настройки lag_tolerance.
Это часто происходит с инкрементальными моделями. При первом запуске инкрементальная модель выполняет полную загрузку без предложения WHERE. При последующих запусках is_incremental() возвращает true и добавляется фильтр, что изменяет скомпилированный SQL. dbt State определяет это как изменение запроса вышестоящей модели и пересобирает все нижестоящие модели, даже те, для которых lag_tolerance ещё не истёк.
Например, fct_orders — инкрементальная модель, от которой зависит agg_orders_daily:
{{ config(materialized='incremental', unique_key='id') }}
select id, amount from {{ ref('raw_orders') }}
{% if is_incremental() %}
where id > (select max(id) from {{ this }})
{% endif %}
{{ config(materialized='table', state={'lag_tolerance': '3h'}) }}
select date_trunc('day', created_at) as day, sum(amount) as total
from {{ ref('fct_orders') }}
group by 1
Когда fct_orders переходит от полной загрузки к инкрементальному запуску, её скомпилированный SQL меняется. При этом запуске agg_orders_daily пересобирается, несмотря на заданный для неё lag_tolerance в 3 часа.
Чтобы помочь вам настроить значения lag_tolerance, страница dbt State на dbt platform предоставляет рекомендации по допустимому отставанию на основе истории сборок ваших моделей за последние 30 дней, позволяя определить, для каких моделей будет полезно увеличить допустимое отставание.
Значение по умолчанию
Если вы не задаёте lag_tolerance, dbt State использует 45m (45 минут).
Примеры
Использование разных допустимых задержек в разных окружениях
Используйте выражение Jinja, чтобы задать меньшую допустимую задержку в промышленном окружении и большую — в остальных. Это позволяет поддерживать актуальность данных в промышленном окружении и сокращать ненужные пересборки при разработке:
models:
+state:
lag_tolerance: "{{ '4h' if target.name == 'prod' else '7d' }}"
В этом примере модели для целевого окружения prod пересобираются, когда с момента последней сборки прошло больше 4 часов и вышестоящие данные изменились. Во всех остальных окружениях модели пересобираются, когда с момента последней сборки прошло больше 7 дней и вышестоящие данные изменились.
Изменение допустимой задержки в зависимости от дня недели
Используйте выражение Jinja, чтобы определить день недели и задать более строгую допустимую задержку в будни, чем в выходные:
models:
+state:
lag_tolerance: "{{ '24h' if modules.datetime.datetime.today().weekday() in (5, 6) else '1h' }}"
В этом примере модели пересобираются, когда с момента последней сборки прошло больше 1 часа (с понедельника по пятницу) или больше 24 часов (с субботы по воскресенье) и вышестоящие данные изменились.
Применение разных допустимых задержек к разным папкам
Задайте разные допустимые задержки для разных частей проекта, указав соответствующие папки:
models:
<your_project>:
marts:
+state:
lag_tolerance: 1d
staging:
+state:
lag_tolerance: 1h
Переопределение для отдельной модели
Переопределите значение по умолчанию, заданное на уровне проекта, для отдельной модели:
models:
- name: my_model
config:
state:
lag_tolerance: 1h