Контракты моделей
Связанная документация
Зачем определять контракт?
Определение модели dbt так же просто, как написание SQL-запроса select
. Ваш запрос естественным образом создает набор данных с именами и типами столбцов на основе выбранных вами столбцов и применяемых трансформаций.
Хотя это идеально подходит для быстрого и итеративного развития, для некоторых моделей постоянное изменение структуры возвращаемого набора данных представляет риск, когда другие люди и процессы запрашивают эту модель. Лучше определить набор предварительных "гарантий", которые определяют структуру вашей модели. Мы назыв аем этот набор гарантий "контрактом". При построении вашей модели dbt проверит, что трансформация вашей модели создаст набор данных, соответствующий ее контракту, или не сможет построить модель.
Где поддерживаются контракты?
В настоящее время контракты моделей поддерживаются для:
- SQL моделей.
- Моделей, материализованных как одна из следующих:
table
view
— Представления предлагают ограниченную поддержку имен столбцов и типов данных, но неconstraints
.incremental
— сon_schema_change: append_new_columns
илиon_schema_change: fail
.
- Определенных платформ данных, но поддерживаемые и применяемые
constraints
варьируются в зависимости от платформы.
Контракты моделей не поддерживаются для:
- Python моделей.
materialized view
илиephemeral
-материализованных SQL моделей.- Пользовательских материал изаций (если не добавлено автором).
- Моделей с рекурсивными в BigQuery.
- Других типов ресурсов, таких как
sources
,seeds
,snapshots
и так далее.
Как определить контракт
Предположим, у вас есть модель с запросом, как:
-- много SQL
final as (
select
customer_id,
customer_name,
-- ... и многое другое ...
from ...
)
select * from final
Чтобы применить контракт модели, установите enforced: true
в конфигурации contract
.
Когда контракт применяется, он должен включать name
и data_type
каждого столбца (где data_type
соответствует одному из тех, которые понимает ваша платформа данных).
Если ваша модель материализована как table
или incremental
, и в зависимости от вашей платформы данных, вы можете дополнительно указать constraints, такие как not_null
(содержащий нулевые значения).
models:
- name: dim_customers
config:
contract:
enforced: true
columns:
- name: customer_id
data_type: int
constraints:
- type: not_null
- name: customer_name
data_type: string
...
При построении модели с определенным контрактом dbt будет делать две вещи по-другому:
- dbt выполнит проверку "предварительного полета", чтобы убедиться, что запрос модели вернет набор столбцов с именами и типами данных, соответствующими тем, которые вы определили. Эта проверка не зависит от порядка столбцов, указанных в вашей модели (SQL) или спецификации YAML.
- dbt включит имена столбцов, типы данных и ограничения в DDL-запросы, которые он отправляет на платформу данных, которые будут применяться при построении или обновлении таблицы модели, и упорядочит столбцы в соответствии с контрактом, а не вашей моделью dbt.
Поддержка ограничений платформы
Выберите вкладку, специфичную для адаптера, для получения дополнительной информации о поддержке ограничений на различных платформах. Ограничения делятся на три категории в зависимости от возможности их определения и применения платформой:
- Определяемые и применяемые — Модель не будет построена, если она нарушает ограничение.
- Определяемые и не применяемые — Платформа поддерживает указание типа ограничения, но модель все равно может быть построена, даже если построение модели нарушает ограничение. Это ограничение существует только для целей метаданных. Этот подход более типичен для облачных хранилищ данных, чем для транзакционных баз данных, где более распространено строгое соблюдение правил.
- Не определяемые и не применяемые — Вы не можете указать тип ограничения для платформы.
- Redshift
- Snowflake
- BigQuery
- Postgres
- Spark
- Databricks
Тип ограничения | Определяемое | Применяемое |
---|---|---|
not_null | ✅ | ✅ |
primary_key | ✅ | ❌ |
foreign_key | ✅ | ❌ |
unique | ✅ | ❌ |
check | ❌ | ❌ |
Тип ограничения | Определяемое | Применяемое |
---|---|---|
not_null | ✅ | ✅ |
primary_key | ✅ | ❌ |
foreign_key | ✅ | ❌ |
unique | ✅ | ❌ |
check | ❌ | ❌ |
Тип ограничения | Определяемое | Применяемое |
---|---|---|
not_null | ✅ | ✅ |
primary_key | ✅ | ❌ |
foreign_key | ✅ | ❌ |
unique | ❌ | ❌ |
check | ❌ | ❌ |
Тип ограничения | Определяемое | Применяемое |
---|---|---|
not_null | ✅ | ✅ |
primary_key | ✅ | ✅ |
foreign_key | ✅ | ✅ |
unique | ✅ | ✅ |
check | ✅ | ✅ |
В настоящее время ограничения not_null
и check
применяются только после построения модели. Из-за этого ограничения платформы dbt считает эти ограничения определяемыми, но не применяемыми, что означает, что они не являются частью контракта модели, так как не могут быть применены во время построения. Эта таблица изменится по мере развития функций.
Тип ограничения | Определяемое | Применяемое |
---|---|---|
not_null | ✅ | ❌ |
primary_key | ✅ | ❌ |
foreign_key | ✅ | ❌ |
unique | ✅ | ❌ |
check | ✅ | ❌ |
В настоящее время ограничения not_null
и check
применяются только после построения модели. Из-за этого ограничения платформы dbt считает эти ограничения определяемыми, но не применяемыми, что означает, что они не являются частью контракта модели, так как не могут быть применены во время построения. Эта таблица изменится по мере развития функций.
Тип ограничения | Определяемое | Применяемое |
---|---|---|
not_null | ✅ | ❌ |
primary_key | ✅ | ❌ |
foreign_key | ✅ | ❌ |
unique | ✅ | ❌ |
check | ✅ | ❌ |
Часто задаваемые вопросы
Для каких моделей следует определять контракты?
Любая модель, соответствующая описанным выше критериям, может определить контракт. Мы рекомендуем определять контракты для "публичных" моделей, на которые полагаются в дальнейшем.
- Внутри dbt: Общие с другими группами, другими командами и другими проектами dbt.
- Вне dbt: Отчеты, панели управления или другие системы и процессы, которые ожидают, что эта модель будет име ть предсказуемую структуру. Вы можете отразить эти дальнейшие использования с помощью exposures.
Чем контракты отличаются от тестов?
Контракт модели определяет структуру возвращаемого набора данных. Если логика модели или входные данные не соответствуют этой структуре, модель не строится.
Тесты данных являются более гибким механизмом для проверки содержимого вашей модели после ее построения. Пока вы можете написать запрос, вы можете запустить тест данных. Тесты данных более настраиваемы, например, с пользовательскими порогами серьезности. Их легче отлаживать после обнаружения сбоев, потому что вы можете запросить уже построенную модель или сохранить записи с ошибками в хранилище данных.
В некоторых случаях вы можете заменить тест данных его эквивалентным ограничением. Это имеет преимущество гарантии проверки во время построения и, вероятно, требует меньше вычислительных ресурсов (стоимости) на вашей платформе данных. Предпосылки для замены теста данных ограничением:
- Убедитесь, что ваша платформа данных может поддерживать и применять необходимое вам ограничение. Большинство платформ применяют только
not_null
. - Материализация вашей модели как
table
илиincremental
(неview
илиephemeral
). - Определение полного контракта для этой модели, указав
name
иdata_type
каждого столбца.
Почему тесты не являются частью контракта? В аналогии с программными API, структура ответа API является контрактом. Качество и надежность ("время безотказной работы") также являются очень важными атрибутами качества API, но они не являются частью контракта как такового. Когда контракт изменяется в обратной несовместимой манере, это является критическим изменением, требующим увеличения основной версии.
Нужно ли определять каждый столбец для контракта?
В настоящее время контракты dbt применяются ко всем столбцам, определенным в модели, и требуют явного указания ожиданий относительно всех этих столбцов. Явное объявление контракта не является случайностью — это очень важная часть этой функции.
В то же время, для моделей с множеством столбцов, мы понимаем, что это может означать много yaml. Мы исследуем возможность поддержки "выведенных" контрактов. Это позволит вам определять ограничения и строгую типизацию данных для подмножества столбцов, при этом все еще обнаруживая критические изменения на других столбцах, сравнивая с той же моделью в производстве. Это не то же самое, что "частичный" контракт, потому что все столбцы в модели все еще проверяются во время выполнения и сопоставляются с тем, что определено явно в в ашем yaml-контракте или неявно с состоянием сравнения. Если вас интересует "выведенный" контракт, пожалуйста, проголосуйте или оставьте комментарий на dbt-core#7432.
Как обрабатываются критические изменения?
При сравнении с предыдущим состоянием проекта dbt будет искать критические изменения, которые могут повлиять на потребителей в дальнейшем. Если обнаружены критические изменения, dbt выдаст ошибку контракта.
К критическим изменениям относятся:
- Удаление существующего столбца
- Изменение типа данных существующего столбца
- Удаление или изменение одного из
constraints
на существующем столбце (dbt версии 1.6 или выше) -
Удаление модели с контрактом путем ее удаления, переименования или отключения (dbt v1.9 или выше).
- модели с версией вызовут ошибку. модели без версии вызовут предупреждение.
Более подробная информация доступна в справочнике по контрактам.