О статическом анализе
dbt v2 полностью понимает SQL вашего проекта, обеспечивая расширенные возможности, такие как проверка с учётом диалекта и точное отслеживание происхождения данных на уровне столбцов.
Это возможно благодаря тому, что его этап компиляции более комплексный, чем у движка dbt v1.x. Когда в dbt v1.x говорилось о компиляции, подразумевался только рендеринг — преобразование строк с шаблонами Jinja в SQL-запрос для отправки в базу данных.
dbt v2 также умеет выполнять рендеринг Jinja, но затем выполняет второй этап: статический анализ, создавая и проверяя логический план для каждого запроса проекта после рендеринга. Этот этап лежит в основе новых возможностей dbt v2.
Принципы статического анализа
В разработке программного обеспечения понятие статического анализа обозначает проверки, которые можно выполнить над кодом до его запуска (статический == не выполняющийся).
Самый строгий статический анализ позволяет быть уверенным: если анализ завершился успешно, код будет выполняться в производственной среде без ошибок компиляции.
Менее строгий статический анализ также предоставляет разработчикам полезную информацию во время работы. Но за всё приходится платить: выигрыш в скорости отклика оборачивается потерей гарантий корректности.
dbt v2 использует настройку static_analysis, чтобы вы могли управлять выполнением статического анализа ваших моделей.
Уникальность dbt v2 заключается в том, что он может статически анализировать не только отдельную модель изолированно, но и каждый запрос по всей цепочке вашего DAG. Даже ваша база данных может проверить только тот запрос, который ей передали! Такие концепции, как теория информационных потоков, — хотя они пока и не реализованы в платформе dbt — опираются на стабильные входные данные и возможность отслеживать столбцы по всему DAG.
Режим baseline: плавный переход с dbt v1
dbt v2 по умолчанию использует режим static_analysis: baseline, созданный по аналогии с подходами инструментов проверки типов и линтинга, такими как подход TypeScript к миграции, функция baseline в basedpyright и строгий и нестрогий режимы Pydantic.
В основе перечисленных инструментов и режима baseline в dbt v2 лежат следующие принципы:
- Плавный переход: обеспечить привычный опыт при первом использовании для пользователей, переходящих с dbt v1.
- Постепенное подключение: предложить понятный путь к освоению дополнительных возможностей dbt v2 со временем.
- Практичная проверка: выявлять большинство ошибок SQL без необходимости полностью перерабатывать проект.
Используйте такой подход к постепенной типизации, чтобы начать с облегчённой проверки, а затем по мере готовности проекта постепенно вводить строгие гарантии.
Что меняет режим baseline
Режим baseline вносит несколько принципиальных изменений в поведение по сравнению с прежним двоичным подходом (выключено/включено):
- Без загрузки удалённых схем — режим baseline не получает схемы из хранилища данных.
- Модульные тесты работают без режима strict — ранее для модульных тестов требовалось полностью включить статический анализ. В режиме baseline они работают сразу.
- Без предупреждений о небезопасной интроспекции — мы больше не предупреждаем о небезопасной интроспекции, хотя в будущем по-прежнему хотели бы помочь вам оценивать её.
Следующая таблица показывает, как режим baseline расширяет доступные возможности без необходимости использовать режим strict.
Сравнение возможностей LSP
Режим baseline открывает значительный набор возможностей без необходимости использовать режим strict. Мы также работаем над тем, чтобы со временем сделать в baseline доступными и другие возможности.
Возможности расширения VS Code в зависимости от настройки статического анализа:
✅ = Доступно | ❌ = Недоступно
| Возможность | off | baseline | strict |
|---|---|---|---|
| Переход к определению/ссылке (кроме столбцов) | ✅ | ✅ | ✅ |
| Отслеживание происхождения данных на уровне таблиц | ✅ | ✅ | ✅ |
| Проверка YAML | ✅ | ✅ | ✅ |
| Рендеринг и предварительный просмотр SQL | ✅ | ✅ | ✅ |
| Модульные тесты | ✅ | ✅ | ✅ |
| Обнаружение синтаксических ошибок | ❌ | ✅ | ✅ |
| Предварительный просмотр результатов CTE | ❌ | ✅ | ✅ |
| Переход к определению/ссылке (столбцы) | ❌ | ❌ | ✅ |
| Автоматический рефакторинг имён столбцов | ❌ | ❌ | ✅ |
| Отслеживание происхождения данных на уровне столбцов | ❌ | ❌ | ✅ |
| Обнаружение ошибок типов данных и сигнатур функций | ❌ | ❌ | ✅ |
- Возможности расширения dbt для VS Code в этой таблице доступны всем пользователям — их доступность зависит от режима статического анализа, а не от вашей учётной записи.
Чтобы узнать, какие функции Snowflake поддерживаются в dbt v2 в режиме strict, обратитесь к разделу Поддержка функций Snowflake
Расширение VS Code и Studio IDE предоставляют CodeLens даже при выключенном статическом анализе, позволяя видеть, для каких моделей статический анализ отключён и почему.
В конечном счёте мы хотим, чтобы все разрабатывали в режиме strict для получения максимальных гарантий. Мы понимаем, что такой переход не может произойти мгновенно, — baseline существует, чтобы сделать его плавным. Многие запланированные возможности (например, локальные вычисления) требуют режима strict. Мы также изучаем возможность автоматически определять типы столбцов за вас: это позволит расширить функциональность режима baseline без необходимости вручную предоставлять информацию о типах.
Обработка интроспекции в режиме baseline
В режиме baseline все результаты статического анализа считаются предупреждениями, а не ошибками — проект может продолжать выполняться, даже если компилятор обнаруживает некорректный или проблемный SQL. Этот раздел хорошо иллюстрирует, зачем нужен такой подход.
Ранее в режиме strict система предполагала, что локальные схемы скомпилированных моделей доступны. В режиме baseline мы больше не можем рассчитывать на наличие полной локальной схемы, поэтому baseline использует удалённую базу данных как источник достоверной информации — аналогично dbt v1.
На практике это означает, что компилятор dbt v2 иногда может отмечать некорректные запросы, возникшие из-за того, что интроспективные запросы вернули пустой результат. Если вы столкнулись с этим, можно:
- Проигнорировать предупреждение
- Построить модель локально
- (Скоро) Использовать
warn_error_options, чтобы отключить предупреждение
Например, рассмотрим запрос с использованием макроса dbt_utils.unpivot:
select * from (
{{
dbt_utils.unpivot(
relation=ref('example_model'),
cast_to='integer',
exclude=['order_id', 'customer_id'],
field_name='product_type',
value_name='quantity'
)
}}
)
Если интроспективный запрос завершается с ошибкой или не возвращает результатов, после рендеринга получается:
select * from (
)
Это некорректный SQL. В режиме baseline dbt v2 показывает предупреждение, чтобы проект мог продолжать выполняться, а вы при этом знали о проблеме:
dbt0101: no viable alternative at input '(
)'
--> models/example_model.sql:17:1
Сценарии миграции
Миграция на dbt v2 может потребовать не только перестановок в YAML. Вот некоторые сценарии, которые могут усложнить миграцию:
- Ограниченный доступ к источникам: у вас нет доступа ко всем источникам и моделям большого проекта dbt.
- Сложные рабочие процессы Jinja: ваш проект активно использует post-hooks и интроспекцию.
- Совместимость пакетов: ваш проект зависит от пакетов, которые пока несовместимы с dbt v2.
- Неподдерживаемые возможности SQL: ваши модели или источники используют сложные типы данных (
STRUCT,ARRAY,GEOGRAPHY) или встроенные функции (AI.PREDICT,JSON_FLATTEN,st_pointfromgeohash), которые пока не поддерживаются в dbt v2.
Установка static_analysis в режим baseline позволяет сразу начать использовать dbt v2, постепенно решая перечисленные задачи. По мере устранения проблем совместимости вы можете переводить отдельные модели или весь проект в режим strict для получения максимальных гарантий проверки.
Краткое сравнение движков
dbt v1:
- Выполняет рендеринг и запуск моделей по одной.
- Никогда не выполняет статический анализ.
dbt v2 (режим baseline — по умолчанию):
- Статически анализирует все модели, выявляя большинство ошибок SQL и обеспечивая привычный процесс миграции.
dbt v2 (режим strict):
- Выполняет рендеринг и статический анализ всех моделей до начала выполнения.
- Гарантирует, что ничего не запустится, пока не будет подтверждена корректность всего проекта.
- Разбирает
CREATE FUNCTIONвsql_headerи хукахon-run-start, а затем регистрирует эти UDF, чтобы при строгой компиляции можно было разрешить вызовы этих функций. Режимыbaselineиoffне регистрируют UDF таким способом. См. Пользовательские функции (UDF) в режимеstrict.
Настройка static_analysis
Вы можете изменить способ применения статического анализа для отдельных моделей проекта. Настройка статического анализа распространяется каскадно от наиболее строгой к наименее строгой. Ниже по цепочке происхождения данных модель может сохранить тот же режим или ослабить его — она не может быть строже своей родительской модели.
Установка static_analysis: strict для модели не задаёт автоматически strict для нижележащих моделей; они сохраняют значение по умолчанию для проекта, если вы не настроите их явно. Правила и примеры приведены в разделах Как режимы распространяются по цепочке происхождения данных и Наследование режима strict.
Модели, использующие пользовательские материализации, следуют тем же правилам, с одним исключением для strict. См. раздел Пользовательские материализации.
Доступны следующие значения настройки static_analysis:
baseline(по умолчанию): выполнять статический анализ SQL. Это рекомендуемая отправная точка для пользователей, переходящих с dbt v1: она обеспечивает плавную миграцию и при этом выявляет большинство ошибок SQL.strict: выполнять статический анализ всего SQL до начала выполнения. Используйте этот режим для максимальных гарантий проверки — ничего не запустится, пока не будет подтверждена корректность всего проекта.off: пропустить анализ SQL для этой модели и всех её потомков.
При отключении статического анализа возможности расширения VS Code, зависящие от понимания SQL, будут недоступны.
Лучше всего задавать static_analysis как настройку отдельной модели или группы моделей. Для отладки также можно использовать флаги CLI --static-analysis strict или --static-analysis off, чтобы переопределить все настройки на уровне моделей.
Постепенное внедрение режима strict
Освоившись с dbt v2 в режиме baseline, вы можете постепенно переводить модели или каталоги в режим strict:
name: jaffle_shop
models:
jaffle_shop:
# Начните со строгого анализа наиболее подготовленных моделей
staging:
+static_analysis: strict
# Сохраните baseline для моделей, требующих доработки
marts:
+static_analysis: baseline
Как режимы распространяются по цепочке происхождения данных
Два правила определяют, какой режим может использовать модель:
- Правило допустимости: модель допускает статический анализ, только если все её вышележащие зависимости допускают его.
- Правило строгости: модель не может быть строже своих родительских моделей. Иерархия строгости:
strict→baseline→off.
Ниже по цепочке модель может сохранить режим родительской модели или ослабить его, но не может сделать его строже:
| Вышележащая модель | Допустимый режим нижележащей модели |
|---|---|
strict | strict, baseline или off |
baseline | baseline или off (не strict) |
off | только off |
Правило строгости существует потому, что baseline не формирует полную проанализированную схему, которая нужна режиму strict от вышележащих моделей. Без этой информации нижележащая модель не может выполнять проверку типов уровня strict. Полное описание см. в разделе Как каскадно распространяются режимы статического анализа.
Наследование режима strict
В отличие от baseline или off, режим strict не распространяется на нижележащие модели. Если вы зададите для модели strict, её нижележащие модели не унаследуют режим strict, если вы не настроите их явно. Чтобы сделать все модели strict, сначала нужно задать +static_analysis: strict для корневых моделей либо использовать общепроектную настройку из следующего раздела на уровне проекта.
Например, в цепочке A → B → C со значением по умолчанию baseline установка strict для A (корневого узла) делает строгой только A — B и C остаются в baseline, если не настроить их отдельно. Чтобы сделать всю цепочку strict, задайте +static_analysis: strict для каждой соответствующей модели или группы либо используйте общепроектную настройку.
Этот подход позволяет получать преимущества строгой проверки там, где это возможно, сохраняя гибкость анализа baseline для моделей, которые пока несовместимы со строгим режимом.
Подробнее о настройках см. в разделах Параметры CLI и Настройки и свойства.
Пользовательские материализации
Модели, использующие пользовательскую материализацию, следуют тем же правилам static_analysis, что и любые другие модели, включая режим baseline по умолчанию и обычные правила каскадного распространения.
Это относится к обоим видам пользовательских материализаций:
- Придуманное вами имя: например,
materialized='my_custom_load'. Их можно найти в настройках моделей. - Встроенное имя: например, ваш собственный макрос с именем
materialization table, default. Их сложнее обнаружить, потому что модели сmaterialized='table'выглядят стандартными, но выполняют ваш код вместо кода dbt.
Пользовательские материализации, изменяющие схему
dbt v2 определяет столбцы модели по её SQL, не анализируя код материализации. Пользовательские операторы create, логика слияния или выдача прав допустимы, если они меняют только способ построения модели и оставляют столбцы неизменными. Но если ваша материализация добавляет или переименовывает столбцы либо меняет их типы данных, схема, выведенная dbt, не будет соответствовать таблице в хранилище данных.
Это в первую очередь затрагивает strict, которому, в отличие от baseline, для проверки типов нужны точные схемы вышележащих моделей. Если вы используете strict, задайте static_analysis: off для моделей с материализацией, изменяющей схему:
{{ config(
materialized='my_custom_load',
static_analysis='off'
) }}
select ...
Поскольку off распространяется каскадно, все нижележащие модели также теряют статический анализ. Чтобы сохранить охват анализа по всему DAG, используйте материализации, изменяющие схему, для моделей, от которых больше ничего не зависит.
Определение режима модели
Настроенный вами режим не всегда совпадает с действующим, поскольку фактический режим модели также зависит от её родительских моделей. И расширение dbt для VS Code, и Studio IDE показывают над каждой моделью CodeLens, который сообщает, когда статический анализ отключён и почему.
Помните, что dbt ls --output json --output-keys config.static_analysis сообщает режим, который вы настроили для каждой модели, а не режим, который v2 определяет после применения правил каскадного распространения.
Примеры настроек
Настройка strict для всего проекта
Многие команды хотят включить режим strict для всего проекта и всех пакетов. Для этого задайте +static_analysis: strict для каждого типа ресурсов в dbt_project.yml в разделе с именем вашего проекта (и в разделах с именами пакетов, если вы хотите включить строгий режим и для них):
models:
my_project:
+static_analysis: strict
seeds:
my_project:
+static_analysis: strict
snapshots:
my_project:
+static_analysis: strict
tests:
my_project:
+static_analysis: strict
unit_tests:
my_project:
+static_analysis: strict
sources:
my_project:
+static_analysis: strict
analyses:
my_project:
+static_analysis: strict
Вместо my_project используйте имя вашего проекта — то же значение, что указано в ключе name: в начале dbt_project.yml (например, jaffle_shop). Чтобы применить strict также к пакету, добавьте ещё одну запись для каждого типа ресурсов, используя имя пакета в качестве ключа; например, в разделе models: добавьте your_package_name:, а под ним — +static_analysis: strict.
Отключение статического анализа для всех моделей пакета:
name: jaffle_shop
models:
jaffle_shop:
marts:
+materialized: table
a_package_with_introspective_queries:
+static_analysis: off
Отключение статического анализа в YAML:
models:
- name: model_with_static_analysis_off
config:
static_analysis: off
Отключение статического анализа для модели, использующей пользовательскую UDF:
{{ config(static_analysis='off') }}
select
user_id,
my_cool_udf(ip_address) as cleaned_ip
from {{ ref('my_model') }}
Можно ли использовать режим strict при разработке и baseline при развёртывании?
Да. Это допустимый и рекомендуемый подход: используйте strict во время разработки для более строгой проверки, а при развёртывании сохраняйте baseline для более быстрых запусков, которые с меньшей вероятностью будут остановлены из-за результатов анализа.
Дополнительные сведения, включая примеры CLI и необязательный подход с использованием переменной окружения, см. в разделе Оптимизация статического анализа для разработки и развёртывания.
Когда следует отключать статический анализ с помощью off?
Благодаря включённому по умолчанию режиму baseline статический анализ реже блокирует выполнение. Отключать его следует только в том случае, если dbt v2 не может разобрать SQL, корректный для выбранной вами базы данных.
Это происходит крайне редко. Если вы столкнулись с такой ситуацией, создайте issue с примером SQL, вызывающего ошибку, чтобы мы могли обновить наши парсеры.
Дополнительная информация о dbt v2
- Журнал изменений dbt v2
- О расширении dbt
- Установка dbt v2
- Краткое руководство по началу работы с dbt v2
- Руководство по обновлению
- Лицензионное соглашение dbt v2