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

Новые концепции

dbt Fusion Engine полностью понимает SQL вашего проекта, что открывает продвинутые возможности, такие как валидация с учётом диалекта и точный lineage на уровне отдельных колонок.

Это возможно благодаря тому, что этап компиляции у него более всеобъемлющий, чем у движка dbt Core. Когда dbt Core говорил о компиляции, под этим понимался только рендеринг — преобразование строк с Jinja-шаблонами в SQL‑запрос для отправки в базу данных.

dbt Fusion engine также умеет рендерить Jinja, но затем выполняет вторую фазу: построение и валидацию логического плана для каждого отрендеренного запроса в проекте с помощью статического анализа. Именно этот этап статического анализа лежит в основе новых возможностей Fusion.

ШагДвижок dbt CoreДвижок dbt Fusion
Рендеринг Jinja в SQL
Построение и статический анализ логического плана
Выполнение отрендеренного SQL
Loading table...

Стратегии рендеринга

Каждая точка представляет шаг выполнения модели (render, analyze, run). Числа отражают порядок шагов по всему DAG. JIT‑шаги отмечены зелёным, AOT‑шаги — фиолетовым.Каждая точка представляет шаг выполнения модели (render, analyze, run). Числа отражают порядок шагов по всему DAG. JIT‑шаги отмечены зелёным, AOT‑шаги — фиолетовым.
 JIT‑рендеринг и выполнение (dbt Core)

dbt Core всегда использует Just In Time (JIT) рендеринг. Он рендерит модель, выполняет её в хранилище, а затем переходит к следующей модели.

 AOT‑рендеринг, анализ и выполнение (dbt Fusion engine)

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‑модель в том виде, в каком она была выполнена в последний раз. Это скорее всего нормально, но может привести к тому, что ошибки будут подняты некорректно (ложноположительный результат) или не будут обнаружены вовсе (ложноотрицательный результат).

 Рендеринг и анализ без выполнения

Обратите внимание, что model_d рендерится AOT, так как не использует интроспекцию, но всё равно должен ждать анализа introspective_model_c.

Вы всё равно получите значительные преимущества от «небезопасного» статического анализа по сравнению с его отсутствием, и мы рекомендуем оставлять его включённым, если только вы не заметили, что он создаёт проблемы. А ещё лучше — подумать, можно ли переписать интроспективный код так, чтобы он подходил для 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.

Примеры конфигураций

Отключение статического анализа для всех моделей в пакете:

dbt_project.yml
name: jaffle_shop

models:
jaffle_shop:
marts:
+materialized: table

a_package_with_introspective_queries:
+static_analysis: off

Отключение статического анализа в YAML:

models/my_udf_using_model.yml
models:
- name: model_with_static_analysis_off
config:
static_analysis: off

Отключение статического анализа для модели, использующей пользовательскую UDF:

models/my_udf_using_model.sql
{{ 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.

Примеры

Нет интроспективных моделей

 AOT‑рендеринг, анализ и выполнение
  • 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_b Fusion рендерит SQL для model_c (используя только что обновлённые данные), анализирует его и выполняет. Все три шага происходят последовательно.
  • AOT‑отрендеренный SQL для model_d анализируется и выполняется.
 Сложный DAG с интроспективной веткой

Как и ожидается, DAG с ветвлением будет AOT‑компилироваться настолько полно, насколько это возможно, прежде чем перейти к JIT‑компонентам, и будет работать с несколькими --threads, если они доступны. В этом примере model_c может начать рендеринг сразу после завершения выполнения model_b, в то время как AOT‑скомпилированные model_x и model_y выполняются параллельно:

Дополнительная информация о Fusion

Fusion — это значительное обновление dbt. Хотя многие рабочие процессы, к которым вы привыкли, остаются без изменений, появляется множество новых идей, а также происходит отказ от ряда старых подходов. Ниже приведён список, охватывающий полный объём текущего релиза движка Fusion, включая вопросы реализации, установки, устаревших возможностей и ограничений:

Нашли ошибку?

0
Loading