# freshness

Используйте конфигурацию `freshness`, чтобы указать, насколько свежими должны быть данные вашего [источника](#source-freshness) или [модели](#model-freshness).

(Версии dbt: v2.0 и новее)

Выполните [`dbt freshness`](https://docs.getdbt.tech/reference/commands/freshness.md), чтобы проверить все источники и модели, для которых настроена проверка свежести данных.

примечание

`dbt source freshness` — это устаревшая команда, которая проверяет актуальность данных *только* в источниках. Она по-прежнему поддерживается для обратной совместимости и продолжает создавать `sources.json`, но в дальнейшем мы рекомендуем использовать `dbt freshness`.

## Конфигурация

Используйте следующие поля для настройки свежести данных источников и моделей, если не указано иное:

| Поле              | Описание                                                                                                                                                                                                                                                                                                |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `warn_after`      | Максимально допустимый возраст самых свежих данных, при превышении которого проверка свежести выдает предупреждение. Требует указания и `count`, и `period`.                                                                                                                                            |
| `error_after`     | Максимально допустимый возраст самых свежих данных, при превышении которого проверка свежести выдает ошибку. Формат такой же, как у `warn_after`.                                                                                                                                                       |
| `loaded_at_field` | Столбец, к которому dbt обращается, чтобы определить временную метку последней загрузки. Обязателен, если метаданные адаптера недоступны.                                                                                                                                                               |
| `loaded_at_query` | SQL-выражение, возвращающее временную метку последней загрузки. Альтернатива `loaded_at_field`. Одновременное указание `loaded_at_query` и `loaded_at_field` для одного ресурса вызывает ошибку разбора. Доступно в dbt v1.10 и более поздних версиях.                                                  |
| `filter`          | Добавляет условие `WHERE` в запрос проверки свежести, чтобы ограничить объем сканируемых данных. Полезно для секционированных таблиц BigQuery или больших таблиц в Snowflake, Databricks или Spark. Не влияет на другие способы использования источника или модели. Не применяется к `loaded_at_query`. |

Можно указать один из параметров `warn_after` и `error_after` или оба. Если ни один из них не задан, dbt не будет проверять свежесть данных этого ресурса. Для каждого из параметров `warn_after` и `error_after` необходимо указать и `count`, и `period`; указание только одного из них приводит к предупреждению при разборе, но вызывает ошибку при выполнении `dbt freshness`.

## Свежесть данных источников

### Файл проекта

dbt\_project.yml

```yaml
sources:
  <resource-path>:
    +freshness:
warn_after:
        count: <positive_integer>
        period: minute | hour | day
```

### Property file

models/\<filename>.yml

```yaml
sources:
  - name: <source_name>
    config:
      freshness: # changed to config in v1.9
        warn_after:
          count: <positive_integer>
          period: minute | hour | day
        error_after:
          count: <positive_integer>
          period: minute | hour | day
        filter: <boolean_sql_expression>
      # changed to config in v1.10
      loaded_at_field: <column_name_or_expression>
      # or use loaded_at_query in v1.10 or higher
      loaded_at_query: <sql_expression>

    tables:
      - name: <table_name>
        config:
          # source.table.config.freshness overrides source.config.freshness
          freshness:
            warn_after:
              count: <positive_integer>
              period: minute | hour | day
            error_after:
              count: <positive_integer>
              period: minute | hour | day
            filter: <boolean_sql_expression>
          loaded_at_field: <column_name_or_expression>
          loaded_at_query: <sql_expression>
```

Настройки актуальности применяются по иерархии:

* Параметры `freshness` и `loaded_at_field` источника применяются ко всем его таблицам.
* Параметры `freshness` и `loaded_at_field` на уровне таблицы источника переопределяют настройки источника.

Чтобы исключить источник из расчёта актуальности, явно укажите `freshness: null`.

Если у источника есть блок `freshness:`, dbt пытается рассчитать его актуальность:

* При заданном `loaded_at_field` dbt выполняет запрос `select`.
* Если `loaded_at_field` не задан, dbt по возможности использует таблицы метаданных хранилища.

(Версии dbt: v1.12 и новее)

Шаблоны в именах таблиц

В BigQuery проверка актуальности по метаданным ненадёжна для источников с подстановочными символами в имени таблицы, например `events_*`.

Чтобы избежать неверных результатов, включите флаг [`bigquery_reject_wildcard_metadata_source_freshness`](https://docs.getdbt.tech/reference/global-configs/bigquery-changes.md#the-bigquery_reject_wildcard_metadata_source_freshness-flag) в `dbt_project.yml`. Тогда dbt выдаст ошибку, если проверка по метаданным используется с подстановочным символом в имени таблицы.

Чтобы проверять актуальность таблиц с такими именами, настройте `loaded_at_field`. Тогда проверка будет выполняться запросом.

### Примеры

#### Использование `loaded_at_field`

```yml
sources:
  - name: jaffle_shop
    config:
      # Cast a date field to timestamp
      loaded_at_field: "completed_date::timestamp"

    tables:
      - name: orders
        config:
          # Cast a non-UTC timestamp to UTC
          loaded_at_field: "convert_timezone('Australia/Sydney', 'UTC', created_at_local)"
          freshness:
            warn_after: {count: 12, period: hour}
```

#### Использование `loaded_at_query`

(Версии dbt: v1.10 и новее)

```yaml
sources:
  - name: jaffle_shop
    tables:
      - name: orders
        loaded_at_query: |
          select max(_sdc_batched_at) from (
            select * from {{ this }}
            where _sdc_batched_at > dateadd(day, -7, current_date)
            qualify count(*) over (partition by _sdc_batched_at::date) > 2000
          )
        config:
          freshness:
            warn_after: {count: 12, period: hour}
```

#### Полный пример

models/\<filename>.yml

```yaml
sources:
  - name: jaffle_shop
    database: raw
    config:
      freshness: # default freshness for all tables
        warn_after: {count: 12, period: hour}
        error_after: {count: 24, period: hour}
      loaded_at_field: _etl_loaded_at

    tables:
      - name: customers # uses the freshness defined above

      - name: orders
        config:
          freshness: # more strict for orders
            warn_after: {count: 6, period: hour}
            error_after: {count: 12, period: hour}
            filter: datediff('day', _etl_loaded_at, current_timestamp) < 2

      - name: product_skus
        config:
          freshness: null # do not check freshness for this table
```

(Версии dbt: v2.0 и новее)

Команда [`dbt freshness`](https://docs.getdbt.tech/reference/commands/freshness.md) выполнит для таблицы `orders` следующий запрос:

### Compiled SQL

```sql
select
  max(_etl_loaded_at) as max_loaded_at,
  convert_timezone('UTC', current_timestamp()) as snapshotted_at
from raw.jaffle_shop.orders
where datediff('day', _etl_loaded_at, current_timestamp) < 2
```

### Jinja SQL

```sql
select
  max({{ loaded_at_field }}) as max_loaded_at,
  {{ current_timestamp() }} as snapshotted_at
from {{ source }}
{% if filter %}
where {{ filter }}
{% endif %}
```

*[Source code](https://github.com/dbt-labs/dbt-adapters/blob/main/dbt-adapters/src/dbt/include/global_project/macros/adapters/freshness.sql#L5-L16)*

(Версии dbt: v2.0 и новее)

## Актуальность модели

Настройка модели `freshness` позволяет:

* **Задать пороги актуальности:** укажите `warn_after` и `error_after`, чтобы задать допустимый возраст данных. Затем запустите `dbt freshness`, чтобы проверить модели и получить предупреждение или ошибку при превышении порогов.
* **Запланировать сборки (`build_after`):** задайте, как часто перестраивать модель после появления новых данных выше по графу. Доступно только на тарифах Enterprise платформы dbt. Параметр `build_after` относится к прежней оркестрации с учётом состояния, которую заменил [dbt State](https://docs.getdbt.tech/docs/deploy/dbt-state-about.md).

### Project file

dbt\_project.yml

```yml
models:
  <resource-path>:
    +loaded_at_field: <column_name>    # or loaded_at_query
    +loaded_at_query: <sql_expression> # alternative to loaded_at_field
    +freshness:
      warn_after: {count: <positive_integer>, period: minute | hour | day}
      error_after: {count: <positive_integer>, period: minute | hour | day}
```

### Property file

models/\<filename>.yml

```yml
models:
  - name: stg_orders
    config:
      loaded_at_field: updated_at    # or loaded_at_query
      freshness:
warn_after: {count: 24, period: hour}
        error_after: {count: 48, period: hour}
```

### SQL file config

models/\<filename>.sql

```sql
{{
    config(
      loaded_at_field="updated_at",
      freshness={
"warn_after": {"count": 24, "period": "hour"},
        "error_after": {"count": 48, "period": "hour"}
      }
    )
}}
```

Поддержка проверок актуальности зависит от материализации. dbt проверяет конфигурацию при разборе и выдаёт ошибку для недопустимых сочетаний.

| Материализация                                               | `loaded_at_field` / `loaded_at_query` | Поведение                                                                                                                                                                                                                                 |
| ------------------------------------------------------------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `table`, `incremental`, `materialized_view`, `dynamic_table` | Необязательно                         | Если не задано, dbt использует метаданные адаптера (например, время последнего изменения таблицы).                                                                                                                                        |
| `view`, `external`                                           | Обязательно                           | Представления не предоставляют метаданные на уровне строк. Задайте `loaded_at_field` или `loaded_at_query` для оценки свежести данных. Пустая строка (`loaded_at_field: ""`) считается отсутствующим значением и вызывает ошибку разбора. |
| `ephemeral`                                                  | Не поддерживается                     | Ничего не материализуется, поэтому оценить свежесть данных невозможно. Вызывает ошибку разбора.                                                                                                                                           |

Неполное правило актуальности, например `warn_after` с `count` без `period`, вызывает предупреждение при разборе для всех материализаций. Команды `dbt run` и `dbt build` выдают предупреждение, но выполняются. Только `dbt freshness` считает это ошибкой. Для моделей `view` и `external` нужен `loaded_at_field` или `loaded_at_query`. Если не указан ни один из них, разбор завершается ошибкой для `dbt run`, `dbt build` и `dbt freshness` независимо от полноты правила.

### Проверка свежести данных между проектами

Для публичных моделей в [dbt Mesh](https://docs.getdbt.tech/docs/mesh/about-mesh.md) dbt сохраняет конфигурацию свежести данных, чтобы зависимые проекты могли проверять свежесть данных вышестоящих моделей без запуска вышестоящего проекта.

Например, `project_a` содержит публичную модель `orders` с настроенной проверкой свежести данных:

```yaml
# project_a: models/orders.yml
models:
  - name: orders
    access: public
    config:
      loaded_at_field: updated_at
      freshness:
        warn_after: {count: 24, period: hour}
        error_after: {count: 48, period: hour}
```

`project_b` зависит от `orders`. Чтобы проверить свежесть данных в `orders`, выполните `dbt freshness` из `project_b` — повторно запускать `project_a` не нужно:

```bash
# run from project_b
dbt freshness --select project_a.orders
```

### Примеры

#### Использование только `warn_after`

```yaml
models:
  - name: stg_orders
    config:
      materialized: table
      freshness:
        warn_after: {count: 24, period: hour}
```

#### Использование `loaded_at_query`

```yaml
models:
  - name: stg_events
    config:
      materialized: table
      freshness:
        warn_after: {count: 6, period: hour}
        error_after: {count: 12, period: hour}
      loaded_at_query: "select max(_loaded_at) from {{ this }} where _batch_complete = true"
```

### Планирование сборок

Оркестрация с учетом состояния теперь называется dbt State

[dbt State](https://docs.getdbt.tech/docs/deploy/dbt-state-about.md) работает со всеми движками и средами: dbt v1, dbt platform и dbt v2

Если вы использовали оркестрацию с учетом состояния до 1 июня 2026 года, вы можете продолжать ее использовать. Когда вы начнете бесплатный пробный период dbt State, он будет продлен сверх стандартных 30 дней. Если продление не применено к вашей учетной записи, обратитесь к команде по работе с вашим аккаунтом. Чтобы начать, ознакомьтесь с разделом [Переход с оркестрации с учетом состояния](https://docs.getdbt.tech/docs/deploy/dbt-state-migration.md).

### Файл проекта

dbt\_project.yml

```yaml
models:
  <resource-path>:
    +freshness:
      build_after: # Available only on dbt platform Enterprise tiers
        count: <positive_integer>
        period: minute | hour | day
        updates_on: any | all # optional, default is `any`
```

### Файл свойств

models/\<filename>.yml

```yml
models:
  - name: stg_orders
    config:
      freshness:
        build_after:  # Available only on dbt platform Enterprise tiers
          count: <positive_integer>
          period: minute | hour | day
          updates_on: any | all # optional, default is `any`
```

### Конфигурация в SQL-файле

models/\<filename>.sql

```sql
{{
    config(
      freshness={
        "build_after": {
          "count": <positive_integer>,
          "period": "minute" | "hour" | "day",
          "updates_on": "any" | "all"
        }
      }
    )
}}
```

Параметр конфигурации `build_after` применяется к оркестрации с учётом состояния (SAO), которая теперь считается устаревшей. `build_after` выполняет повторную сборку моделей *только при наличии новых данных в источниках или вышестоящих моделях*. Это полезно для моделей, которые зависят от других моделей, но требуют лишь периодического обновления.

`freshness` работает совместно с оркестрацией джобов dbt и помогает определить, когда модели действительно нужно пересобирать в рамках запланированного запуска. При каждом запуске джоба dbt гарантирует, что модели выполняются только при необходимости, что позволяет избежать избыточных сборок. Для этого dbt:

* Проверяет, появились ли новые данные для модели
* Убеждается, что с момента последней сборки прошло достаточно времени, на основе параметров `count` и `period`

Для источников и апстрим-моделей (в случае mesh) dbt определяет «новизну» данных на основе пользовательских вычислений freshness (если они настроены). Если freshness источника превышает заданный порог warning или error, dbt выдает предупреждение или ошибку во время сборки.

Конфигурация состоит из следующих частей:

| Конфигурация       | Описание                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `build_after`      | Доступно только на тарифах Enterprise платформы dbt. Конфигурация, вложенная в `freshness`. Определяет, следует ли пересобирать модель при наличии новых данных, исходя из того, прошло ли с момента последней сборки модели время, заданное параметрами count и period. Хотя dbt проверяет наличие новых данных при каждом запуске задания, `build_after` гарантирует, что модель будет пересобрана только в том случае, если прошло достаточно времени и появились новые данные.                                                                                                             |
| `count` и `period` | Указывают, как часто dbt должен проверять наличие новых данных. Например, `count: 4, period: hour` означает, что dbt будет выполнять проверку каждые 4 часа. При настройке `build_after` обязательны оба параметра: `count` и `period`.                                                                                                                                                                                                                                                                                                                                                        |
| `updates_on`       | Необязательный параметр. Значение по умолчанию — `any`. Определяет, когда изменения в вышестоящих данных должны запускать сборку в рамках задания. Используйте следующие значения:<br />- `any` (по умолчанию): модель будет собрана, как только с момента последней сборки появятся новые данные в *любом* непосредственно вышестоящем узле. Быстрее, но может увеличить расходы.<br />- `all`: модель будет собрана только тогда, когда с момента последней сборки появятся новые данные во *всех* непосредственно вышестоящих узлах. Меньше расходов, но больше условий для запуска сборки. |

Если вы используете [dbt State](https://docs.getdbt.tech/docs/deploy/dbt-state-about.md), настройки `build_after` перенесены из блока `freshness` в блок `state`:

| Оркестрация с учётом состояния                                 | dbt State                                                                                                          |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `freshness.build_after.count` + `freshness.build_after.period` | [`state.lag_tolerance`](https://docs.getdbt.tech/reference/resource-configs/lag-tolerance.md)                     |
| `freshness.build_after.updates_on`                             | [`state.require_fresh_data_from`](https://docs.getdbt.tech/reference/resource-configs/require-fresh-data-from.md) |

Дополнительную информацию см. в разделе [Миграция с оркестрации с учётом состояния](https://docs.getdbt.tech/docs/deploy/dbt-state-migration.md).

#### Значение по умолчанию

Значение по умолчанию для ключа `build_after`:

```yaml
build_after:
  count: 0
  period: minute
  updates_on: any
```

Значение по умолчанию для `updates_on` — `any`. Это означает, что по умолчанию модель будет строиться при каждом запуске задания по расписанию при наличии любого объёма новых данных.

#### Примеры

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

##### Реже

Вы можете настроить модель так, чтобы она запускалась реже (что снижает затраты): сборка будет выполняться не чаще одного раза за заданный интервал времени и только при наличии новых данных.

```yaml
models:
  - name: stg_wizards
    config:
      freshness:
        build_after:
          count: 4
          period: hour
          updates_on: all
  - name: stg_worlds
    config:
      freshness:
        build_after:
          count: 4
          period: hour
          updates_on: all
```

Когда срабатывает state-aware orchestration job, dbt проверяет два условия:

* Появились ли новые исходные данные во всех апстрим-моделях
* Были ли модели `stg_wizards` и `stg_worlds` собраны более 4 часов назад

Когда выполняются *оба* условия, dbt собирает модель. В этом случае используется настройка `updates_on: all`. Если источник `raw.wizards` получил новые данные, но `stg_wizards` и `stg_worlds` были собраны 3 часа назад, сборка не произойдет.

##### Более частые запуски

Если вы хотите запускать модель чаще, можно настроить её так, чтобы она строилась, как только в *любой* из её зависимостей появляются новые данные, не дожидаясь обновления всех зависимостей.

```yaml
models:
  - name: stg_wizards
    config:
      freshness:
        build_after:
          count: 1
          period: hour
          updates_on: any
  - name: stg_worlds
    config:
      freshness:
        build_after:
          count: 1
          period: hour
          updates_on: any
```

При запуске state-aware orchestration job dbt проверяет:

* Если новые исходные данные доступны хотя бы для одной вышестоящей модели.
* Если `stg_wizards` или `stg_worlds` не была построена за последний час.

Если выполнены *оба* условия, dbt перестраивает модель. Если ни у одной из моделей нет новых данных, ничего построено не будет.

В этом примере, поскольку задано `updates_on: any`, даже если новые данные есть только в источнике `raw.wizards` и за последний час была построена только модель `stg_wizards` (а `stg_worlds` не обновлялась), dbt всё равно построит модель, поскольку для этого достаточно одного обновлённого источника и одной подходящей (устаревшей) модели.

##### Настраиваемая периодичность

Вы также можете использовать собственную логику с `build_after`, чтобы задать разную периодичность для разных дней или пропускать построения в определённый период (например, в выходные).

### Project file

dbt\_project.yml

```yaml
+freshness:
  build_after:
    # если сегодня суббота или воскресенье, ждать минимум 48 часов перед следующей сборкой
    # в противном случае — ждать минимум 1 час
    count: "{{ 48 if modules.datetime.datetime.today().weekday() in (5, 6) else 1 }}"
    period: hour
    updates_on: any
```

### SQL file config

models/\<filename>.sql

```sql
{{
    config(
      freshness={
        "build_after": {
          "count": 48 if modules.datetime.datetime.today().weekday() in (5, 6) else 1,
          "period": "hour",
          "updates_on": "any"
        }
      }
    )
}}
```
