Новые концепции
dbt Fusion Engine полностью понимает SQL вашего проекта, что открывает продвинутые возможности, такие как валидация с учётом диалекта и точный lineage на уровне отдельных колонок.
Это возможно благодаря тому, что этап компиляции у него более всеобъемлющий, чем у движка dbt Core. Когда dbt Core говорил о компиляции, под этим понимался только рендеринг — преобразование строк с Jinja-шаблонами в SQL‑запрос для отправки в базу данных.
dbt Fusion engine также умеет рендерить Jinja, но затем выполняет вторую фазу: построение и валидацию логического плана для каждого отрендеренного запроса в проекте с помощью статического анализа. Именно этот этап статического анализа лежит в основе новых возможностей Fusion.
| Loading table... |
Стратегии рендеринга
Каждая точка представляет шаг выполнения модели (render, analyze, run). Числа отражают порядок шагов по всему DAG. JIT‑шаги отмечены зелёным, AOT‑шаги — фиолетовым.dbt Core всегда использует Just In Time (JIT) рендеринг. Он рендерит модель, выполняет её в хранилище, а затем переходит к следующей модели.
dbt Fusion Engine по умолчанию использует Ahead of Time (AOT) рендеринг и анализ. Он рендерит все модели проекта, затем строит и статически анализирует логический план каждой модели, и только после этого начинает выполнять модели в хранилище.
Рендеря и анализируя все модели заранее и начиная выполнение только после того, как доказана их корректность, dbt Fusion Engine избегает ненужного расходования ресурсов хранилища. Для сравнения, SQL‑ошибки в моделях, запускаемых движком dbt Core, выявляются самой базой данных только во время выполнения.
Рендеринг интроспективных запросов
Исключением из AOT‑рендеринга являются интроспективные модели — модели, у которых отрендеренный SQL зависит от результатов запроса к базе данных. Модели, содержащие макросы вроде run_query() или dbt_utils.get_column_values(), считаются интроспективными. Интроспекция создаёт проблемы для AOT‑рендеринга, потому что:
- Большинство интроспективных запросов выполняются поверх результатов более ранней модели в DAG, которая может ещё не существовать в базе данных во время AOT‑рендеринга.
- Даже если модель существует в базе данных, она может быть неактуальной до тех пор, пока модель не будет обновлена.
dbt Fusion Engine переключается на JIT‑рендеринг для интроспективных моделей, чтобы рендерить их так же, как это делает dbt Core.
Обратите внимание, что макросы вроде adapter.get_columns_in_relation() и dbt_utils.star() могут быть отрендерены и проанализированы заранее, при условии что Relations, которые они исследуют, сами по себе не являются динамическими. Это возможно потому, что dbt Fusion Engine загружает схемы в память в рамках процесса компиляции.
Принципы статического анализа
Идея статического анализа заключается в том, чтобы гарантировать: если модель компилируется без ошибок в разработке, то при деплое она также выполнится без ошибок компиляции. Интроспективные запросы могут нарушить это обещание, поскольку позволяют изменить отрендеренный запрос после того, как модель уже закоммичена в систему контроля версий.
dbt Fusion Engine использует конфигурацию static_analysis, чтобы дать вам контроль над тем, как выполняется статический анализ моделей.
Уникальность dbt Fusion Engine в том, что он способен статически анализировать не одну модель в изоляции, а каждый запрос от одного конца DAG до другого. Даже сама база данных может валидировать только тот запрос, который перед ней! Такие концепции, как теория потоков информации — хотя они и не внедрены в платформу dbt пока — опираются на стабильные входные данные и возможность отслеживать колонки по всему DAG.
Статический анализ и интроспективные запросы
Когда Fusion сталкивается с интроспективным запросом, соответствующая модель переключается на JIT‑рендеринг (как описано выше). Эта модель и все её потомки также будут переведены на JIT‑статический анализ. Мы называем JIT‑статический анализ «небезопасным», потому что он всё ещё отлавливает большинство SQL‑ошибок и предотвращает выполнение некорректной модели, но делает это только после того, как upstream‑модели уже были материализованы.
Эта классификация означает, что Fusion больше не может на 100 % гарантировать соответствие между тем, что он анализирует, и тем, что в итоге будет выполнено. Наиболее распространённый реальный пример, когда небезопасный статический анализ может вызвать проблемы, — это отдельный шаг dbt compile (в отличие от компиляции, происходящей как часть dbt run).
Во время dbt run JIT‑рендеринг гарантирует, что код downstream‑модели будет соответствовать текущему состоянию хранилища, но отдельная компиляция не обновляет upstream‑модели. В этом сценарии Fusion читает upstream‑модель в том виде, в каком она была выполнена в последний раз. Это скорее всего нормально, но может привести к тому, что ошибки будут подняты некорректно (ложноположительный результат) или не будут обнаружены вовсе (ложноотрицательный результат).
Вы всё равно получите значительные преимущества от «небезопасного» статического анализа по сравнению с его отсутствием, и мы рекомендуем оставлять его включённым, если только вы не заметили, что он создаёт проблемы. А ещё лучше — подумать, можно ли переписать интроспективный код так, чтобы он подходил для AOT‑рендеринга и статического анализа.
Краткое сравнение движков
dbt Core:
- рендерит все модели just‑in‑time
- никогда не выполняет статический анализ
dbt Fusion engine:
- рендерит все модели заранее, если только они не используют интроспективные запросы
- статически анализирует все модели, по умолчанию ahead‑of‑time, если только сама модель или её родители не были отрендерены just‑in‑time, в этом случае этап статического анализа также выполняется just‑in‑time.
Настройка static_analysis
Помимо поведения по умолчанию, описанного выше, вы всегда можете изменить то, как статический анализ применяется к конкретным моделям в вашем проекте. Помните, что модель может участвовать в статическом анализе только в том случае, если все её родительские модели также подходят для него.
Доступные параметры конфигурации static_analysis:
on: Выполнять статический анализ SQL. Значение по умолчанию для неинтроспективных моделей, зависит от AOT‑рендеринга.unsafe: Выполнять статический анализ SQL. Значение по умолчанию для интроспективных моделей. Всегда использует JIT‑рендеринг.off: Пропустить SQL‑анализ для этой модели и всех её потомков.
При отключении статического анализа функции расширения VS Code, зависящие от понимания SQL, будут недоступны.
Лучшее место для настройки static_analysis — это конфигурация на уровне отдельной модели или группы моделей. В качестве вспомогательного инструмента для отладки вы также можете использовать CLI‑флаги --static-analysis off или --static-analysis unsafe, чтобы переопределить конфигурацию для всех моделей.
Подробнее о конфигурациях см. CLI options и Configurations and properties.
Примеры конфигураций
Отключение статического анализа для всех моделей в пакете:
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') }}
Когда стоит выключать static analysis (off)?
Статический анализ может ошибочно падать на корректных запросах, если они содержат:
- синтаксис или нативные функции, которые dbt Fusion Engine не распознаёт. Пожалуйста, создайте issue в дополнение к отключению статического анализа.
- пользовательские функции (UDF), которые dbt Fusion Engine не распознаёт. В этом случае потребуется временно отключить статический анализ. Нативная поддержка компиляции UDF появится в будущей версии — см. dbt-fusion#69.
- динамический SQL, например PIVOT ANY в Snowflake, который невозможно проанализировать статически. Вы можете отключить статический анализ, переписать pivot с явными именами колонок или создать динамический pivot в Jinja.
- высоковолатильные данные, питающие интроспективный запрос, при отдельном запуске
dbt compile. Поскольку шагdbt compileне выполняет модели, он использует устаревшие данные или обращается к другой среде при выполнении интроспективных запросов. Чем чаще меняются входные данные, тем выше вероятность того, что это расхождение приведёт к ошибке компиляции. Прежде чем отключать статический анализ, подумайте, действительно ли необходимы такие отдельные вызовыdbt compile.
Примеры
Нет интроспективных моделей
- Fusion рендерит каждую модель по порядку.
- Затем он по порядку выполняет статический анализ логического плана каждой модели.
- Наконец, он выполняет отрендеренный SQL каждой модели. Ничего не сохраняется в базе данных до тех пор, пока Fusion не провалидирует весь проект.
Интроспективная модель с unsafe static analysis
Представим, что мы обновили model_c, добавив в неё интроспективный запрос (например, dbt_utils.get_column_values). Пусть он обращается к model_b, но реакция dbt Fusion Engine будет одинаковой независимо от того, что именно делает интроспекция.
- Во время парсинга Fusion обнаруживает интроспективный запрос в
model_c. Он переключаетmodel_cна JIT‑рендеринг и переводитmodel_c+на JIT‑статический анализ. model_aиmodel_bпо‑прежнему подходят для AOT‑компиляции, поэтому Fusion обрабатывает их так же, как и в примере без интроспекции.model_dпо‑прежнему подходит для AOT‑рендеринга (но не для анализа).- После выполнения
model_bFusion рендерит SQL дляmodel_c(используя только что обновлённые данные), анализирует его и выполняет. Все три шага происходят последовательно. - AOT‑отрендеренный SQL для
model_dанализируется и выполняется.
Как и ожидается, DAG с ветвлением будет AOT‑компилироваться настолько полно, насколько это возможно, прежде чем перейти к JIT‑компонентам, и будет работать с несколькими --threads, если они доступны. В этом примере model_c может начать рендеринг сразу после завершения выполнения model_b, в то время как AOT‑скомпилированные model_x и model_y выполняются параллельно:
Дополнительная информация о Fusion
Fusion — это значительное обновление dbt. Хотя многие рабочие процессы, к которым вы привыкли, остаются без изменений, появляется множество новых идей, а также происходит отказ от ряда старых подходов. Ниже приведён список, охватывающий полный объём текущего релиза движка Fusion, включая вопросы реализации, установки, устаревших возможностей и ограничений:
- О движке dbt Fusion
- О расширении dbt
- Новые концепции в Fusion
- Матрица поддерживаемых возможностей
- Установка Fusion CLI
- Установка расширения VS Code
- Трек релизов Fusion
- Быстрый старт для Fusion
- Руководство по обновлению
- Лицензирование Fusion