Перейти к основному содержимому

Defer

Defer — это мощная функция, которая позволяет запускать подмножество моделей или тестов в песочнице без необходимости сначала строить их родительские модели. Это может сэкономить время и вычислительные ресурсы, когда вы хотите протестировать небольшое количество моделей в большом проекте.

Используйте 'defer', чтобы модифицировать модели в конце конвейера, указывая на производственные модели, вместо того чтобы запускать все вышестоящие.Используйте 'defer', чтобы модифицировать модели в конце конвейера, указывая на производственные модели, вместо того чтобы запускать все вышестоящие.

Defer требует, чтобы манифест из предыдущего вызова dbt был передан в флаг --state или переменную окружения. Вместе с методом выбора state:, эти функции позволяют реализовать "Slim CI". Подробнее о state.

Альтернативной командой, которая выполняет аналогичную функциональность для других случаев использования, является dbt clone — см. документацию по clone для получения дополнительной информации.

Можно использовать отдельное состояние для state:modified и --defer, передавая пути к разным манифестам для каждого из --state/DBT_STATE и --defer-state/DBT_DEFER_STATE. Это позволяет более точно контролировать случаи, когда вы хотите сравнить с логическим состоянием из одной среды или прошлого момента времени и отложить применение состояния из другой среды или момента времени. Если --defer-state не указан, откладывание будет использовать манифест, переданный в --state. В большинстве случаев вы захотите использовать одно и то же состояние для обоих: сравнивать логические изменения с производством, а также "переключаться" на производственную среду для не построенных вышестоящих ресурсов.

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

dbt run --select [...] --defer --state path/to/artifacts
dbt test --select [...] --defer --state path/to/artifacts

По умолчанию dbt использует пространство имен target для разрешения вызовов ref.

Когда --defer включен, dbt разрешает вызовы ref, используя манифест состояния, но только если:

  1. Узел не входит в число выбранных узлов, и
  2. Он не существует в базе данных (или используется --favor-state).

Эфемерные модели никогда не откладываются, так как они служат "переходами" для других вызовов ref.

При использовании defer вы можете выбирать из производственных наборов данных, наборов данных для разработки или их комбинации. Обратите внимание, что это может привести к неожиданным результатам:

  • если вы применяете ограничения, специфичные для среды, в разработке, но не в производстве, так как вы можете выбрать больше данных, чем ожидали
  • при выполнении тестов, которые зависят от нескольких родителей (например, relationships), так как вы тестируете "между" средами

Откладывание требует установки как --defer, так и --state, либо путем явной передачи флагов, либо путем установки переменных окружения (DBT_DEFER и DBT_STATE). Если вы используете dbt Cloud, прочитайте о настройке CI задач.

Предпочтение состояния

Когда передан --favor-state, dbt отдает приоритет определениям узлов из каталога --state. Однако это не применяется, если узел также является частью выбранных узлов.

Пример

В моей локальной среде разработки я создаю все модели в моей целевой схеме, dev_alice. В производстве те же модели создаются в схеме с именем prod.

Я получаю доступ к dbt-сгенерированным артефактам (а именно manifest.json) из производственного запуска и копирую их в локальный каталог под названием prod-run-artifacts.

run

Я работал над model_b:

models/model_b.sql
select

id,
count(*)

from {{ ref('model_a') }}
group by 1

Я хочу протестировать свои изменения. В моей схеме разработки, dev_alice, ничего не существует.

dbt run --select "model_b"
target/run/my_project/model_b.sql
create or replace view dev_me.model_b as (

select

id,
count(*)

from dev_alice.model_a
group by 1

)

Если я ранее не запускал model_a в этой среде разработки, dev_alice.model_a не будет существовать, что вызовет ошибку базы данных.

test

У меня также есть тест relationships, который устанавливает ссылочную целостность между model_a и model_b:

models/resources.yml
version: 2

models:
- name: model_b
columns:
- name: id
tests:
- relationships:
to: ref('model_a')
field: id

(Немного глупо, так как все данные в model_b должны были поступить из model_a, но давайте предположим это.)

dbt test --select "model_b"
target/compiled/.../relationships_model_b_id__id__ref_model_a_.sql
select count(*) as validation_errors
from (
select id as id from dev_alice.model_b
) as child
left join (
select id as id from dev_alice.model_a
) as parent on parent.id = child.id
where child.id is not null
and parent.id is null

Тест relationships требует как model_a, так и model_b. Поскольку я не построил model_a в своем предыдущем dbt run, dev_alice.model_a не существует, и этот тестовый запрос не выполняется.

Связанные документы

0