Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Materialized views

Поддерживается в ClickHouse

Материализация materialized_view должна представлять собой SELECT из существующей исходной таблицы. В отличие от PostgreSQL, materialized view в ClickHouse не является «статическим» объектом (и для неё не существует соответствующей операции REFRESH). Вместо этого она работает как триггер вставки: новые строки вставляются в целевую таблицу за счёт применения заданного преобразования SELECT к строкам, вставляемым в исходную таблицу. Подробнее о том, как работают materialized view в ClickHouse, см. в документации ClickHouse по materialized view.

Как управляется целевая таблица

Когда вы используете материализацию materialized_view, dbt-clickhouse должен создать и materialized view, и целевую таблицу, в которую вставляются преобразованные строки. Управлять целевой таблицей можно двумя способами:

Подход Описание Статус
Неявная целевая таблица dbt-clickhouse автоматически создает целевую таблицу и управляет ею в рамках той же модели. Схема целевой таблицы выводится из SQL materialized view. Стабильный
Явная целевая таблица Вы определяете целевую таблицу как отдельную материализацию table и ссылаетесь на нее из модели materialized view с помощью макроса materialization_target_table(). Materialized view создается с предложением TO, указывающим на эту таблицу. Эта возможность доступна начиная с dbt-clickhouse версии 1.10. Внимание: эта возможность находится в статусе бета, и API может измениться на основе отзывов сообщества. Бета

Выбранный подход влияет на то, как обрабатываются изменения схемы, полные обновления и конфигурации с несколькими materialized view. В следующих разделах каждый подход описан подробно.

Материализация с неявной целевой таблицей

Это поведение по умолчанию. Когда вы определяете модель materialized_view, адаптер:

  1. Создаёт целевую таблицу с именем модели
  2. Создаёт в ClickHouse materialized view с именем <model_name>_mv

Схема целевой таблицы выводится на основе столбцов в операторе SELECT materialized view. Все ресурсы (целевая таблица + materialized view) используют одну и ту же конфигурацию модели.

-- models/events_mv.sql
{{
    config(
        materialized='materialized_view',
        engine='SummingMergeTree()',
        order_by='(event_date, event_type)'
    )
}}

SELECT
    toStartOfDay(event_time) AS event_date,
    event_type,
    count() AS total
FROM {{ source('raw', 'events') }}
GROUP BY event_date, event_type

См. тестовый файл с дополнительными примерами.

Несколько materialized view

ClickHouse позволяет нескольким materialized view записывать строки в одну и ту же целевую таблицу. Чтобы поддержать это в dbt-clickhouse при использовании подхода с неявной целевой таблицей, вы можете создать UNION в файле модели, заключив SQL для каждого materialized view между комментариями вида --my_mv_name:begin и --my_mv_name:end.

Например, следующий код создаст два materialized view, которые будут записывать данные в одну и ту же целевую таблицу модели. Имена materialized view будут иметь вид <model_name>_mv1 и <model_name>_mv2:

--mv1:begin
select a,b,c from {{ source('raw', 'table_1') }}
--mv1:end
union all
--mv2:begin
select a,b,c from {{ source('raw', 'table_2') }}
--mv2:end

Как изменять схему целевой таблицы

Начиная с dbt-clickhouse версии 1.9.8, вы можете управлять тем, как изменяется схема целевой таблицы, когда dbt run обнаруживает различия в столбцах в SQL-коде materialized view.

{{config(
    materialized='materialized_view',
    engine='MergeTree()',
    order_by='(id)',
    on_schema_change='fail'  # этот параметр
)}}

По умолчанию dbt не применяет никаких изменений к целевой таблице (значение настройки — ignore), но вы можете изменить эту настройку, чтобы она вела себя так же, как config on_schema_change в incremental-моделях.

Кроме того, эту настройку можно использовать как механизм защиты. Если задать для неё значение fail, сборка завершится ошибкой, если столбцы в SQL materialized view отличаются от столбцов в целевой таблице, созданной при первом dbt run.

Догрузка данных

По умолчанию при создании или повторном создании materialized view (MV) целевая таблица сначала заполняется историческими данными, и только после этого создаётся сама materialized view (catchup=True). Это поведение можно отключить, установив параметру catchup значение False.

{{config(
    materialized='materialized_view',
    engine='MergeTree()',
    order_by='(id)',
    catchup=False  # этот параметр
)}}
Операция catchup: True (по умолчанию) catchup: False
Первоначальное развертывание (dbt run) В целевую таблицу выполняется дозагрузка исторических данных Целевая таблица создается пустой
Полное обновление (dbt run --full-refresh) Целевая таблица пересоздается и дозагружается Целевая таблица пересоздается пустой, существующие данные теряются
Обычная работа materialized view обрабатывает новые вставки materialized view обрабатывает новые вставки

Материализация с явной целевой таблицей (бета)

По умолчанию dbt-clickhouse создает и управляет и целевой таблицей, и materialized view в рамках одной модели (подход с неявной целевой таблицей, описанный выше). У этого подхода есть ряд ограничений:

  • Все ресурсы (целевая таблица + MV) используют одну и ту же конфигурацию. Если несколько MV указывают на одну и ту же целевую таблицу, их нужно определять вместе с помощью синтаксиса UNION ALL.
  • Этими ресурсами нельзя управлять по отдельности — все они должны описываться в одном и том же файле модели.
  • Нельзя легко задать имя для каждой MV.
  • Все настройки общие для целевой таблицы и MV, поэтому сложно настраивать каждый ресурс отдельно и понимать, какая конфигурация к какому ресурсу относится.

Возможность явной целевой таблицы позволяет определить целевую таблицу отдельно как обычную материализацию table, а затем ссылаться на нее из моделей materialized view.

Преимущества

  • Полностью разделённые ресурсы: Теперь каждый ресурс можно определять отдельно, что улучшает читаемость
  • Соответствие ресурсов 1:1 между dbt и CH: Теперь вы можете использовать инструменты dbt, чтобы управлять ими и изменять их по отдельности.
  • Теперь доступны разные конфигурации: Теперь к каждому из них можно применять отдельную конфигурацию.
  • Больше не нужно придерживаться соглашений об именовании: Теперь все ресурсы создаются с использованием заданного вами имени, а не пользовательского имени с добавлением _mv для MV.

Ограничения

  • Определение целевой таблицы не вполне естественно для dbt: это не SQL-запрос, который читает из исходной таблицы, поэтому здесь вы лишаетесь проверок dbt. SQL materialized view по-прежнему будет проверяться с помощью утилит dbt, а его совместимость со столбцами целевой таблицы — на уровне CH.
  • Мы обнаружили несколько проблем, связанных с ограничениями функции ref(): она нужна, чтобы ссылаться на модели друг из друга, но её можно использовать только для ссылок на вышестоящие модели, а не на нижестоящие. Это создаёт определённые сложности для данной реализации. Мы создали issue в репозитории dbt-core и сейчас обсуждаем с их командой возможные решения (dbt-labs/dbt-core#12319):
    • Когда ref() вызывается внутри блока config, она возвращает текущую модель, а не ту, на которую должна ссылаться. Из-за этого мы не можем определить её в секции config() и вынуждены использовать комментарий, чтобы добавить эту зависимость. Мы придерживаемся того же подхода, что описан в документации dbt: вариант с "–depends_on:".
    • ref() нам подходит, поскольку заставляет сначала создать целевую таблицу, но на графе зависимостей в сгенерированной документации целевая таблица будет показана как ещё одна вышестоящая зависимость, а не как нижестоящая, из-за чего это немного сложнее понять.
    • unit-test также вынуждает нас задавать данные для целевой таблицы, даже если по задумке чтения из неё быть не должно. Обходной путь здесь простой — оставить данные для этой таблицы пустыми.

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

Шаг 1: Определите целевую таблицу как обычную табличную модель

Модель events_daily.sql:

{{
    config(
        materialized='table',
        engine='SummingMergeTree()',
        order_by='(event_date, event_type)',
        partition_by='toYYYYMM(event_date)'
    )
}}

SELECT
    toDate(now()) AS event_date,
    '' AS event_type,
    toUInt64(0) AS total
WHERE 0  -- Создаёт пустую таблицу с правильной схемой

Это обходной путь, о котором мы упоминаем в разделе ограничений. Здесь вы можете потерять часть проверок dbt, но схема по-прежнему будет проверяться на уровне ClickHouse.

Шаг 2: Определите materialized view, указывающие на целевую таблицу

Например, можно определить разные MV в разных моделях, в том числе направив их в одну и ту же целевую таблицу. Обратите внимание на новый вызов макроса {{ materialization_target_table(ref('events_daily')) }}, который задаёт целевую таблицу для MV.

Модель page_events_aggregator.sql:

{{ config(materialized='materialized_view') }}
{{ materialization_target_table(ref('events_daily')) }}

SELECT
    toStartOfDay(event_time) AS event_date,
    event_type,
    count() AS total
FROM {{ source('raw', 'page_events') }}
GROUP BY event_date, event_type

Модель mobile_events_aggregator.sql:

{{ config(materialized='materialized_view') }}
{{ materialization_target_table(ref('events_daily')) }}

SELECT
    toStartOfDay(event_time) AS event_date,
    event_type,
    count() AS total
FROM {{ source('raw', 'mobile_events') }}
GROUP BY event_date, event_type

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

При использовании явных целевых таблиц, помимо общих конфигураций материализации и конфигураций для таблиц, применяются следующие конфигурации:

Для целевой таблицы (materialized='table'):

Параметр Описание По умолчанию
mv_on_schema_change Определяет, как обрабатывать изменения схемы, когда таблица используется MV, управляемыми dbt. Поведение соответствует конфигурации on_schema_change в инкрементных моделях. Внимание: модель materialized='table' будет вести себя как обычно, если на неё не ссылаются MV, поэтому даже если этот параметр задан, он будет проигнорирован. Если таблица является целевой для MV, значение этой конфигурации по умолчанию будет mv_on_schema_change='fail' для защиты данных в этих таблицах.
repopulate_from_mvs_on_full_refresh При --full-refresh вместо выполнения SQL таблицы перестраивает её, выполняя INSERT-SELECT с использованием SQL всех MV, указывающих на неё. False

Для materialized view (materialized='materialized_view'):

Параметр Описание По умолчанию
catchup Следует ли выполнять дозагрузку исторических данных при создании MV. True

Основные операции

Полное обновление с явными целевыми таблицами

При использовании --full-refresh явные целевые таблицы будут пересозданы (поэтому вы можете потерять данные, если в ходе этого процесса продолжается ингестия). Поведение будет различаться в зависимости от конфигурации:

Вариант 1: поведение --full-refresh по умолчанию. Всё будет пересоздано, но во время пересоздания MV целевая таблица будет пустой или загруженной лишь частично.

Всё будет удалено и создано заново. Если вы хотите повторно выполнить вставку данных с помощью SQL для MV, оставьте параметр catchup=True:

-- models/page_events_aggregator.sql
{{ config(
    materialized='materialized_view',
    catchup=True  -- это значение по умолчанию, поэтому его не нужно указывать явно.
) }}
{{ materialization_target_table(ref('events_daily')) }}
...

Вариант 2: Я хочу заново создать целевую таблицу и не хочу, чтобы во время пересоздания MV читались пустые данные.

Если вам сначала нужно обновить SQL у MV, вы можете задать в них catchup=False, а затем выполнить dbt run или dbt run --full-refresh для MV. Убедитесь, что MV созданы до запуска --full-refresh для целевой таблицы, так как при этом используются определения MV из ClickHouse.

Установите repopulate_from_mvs_on_full_refresh=True в модели целевой таблицы. При выполнении dbt run --full-refresh произойдет следующее:

  1. Будет создана новая временная таблица
  2. Будет выполнен INSERT-SELECT с использованием SQL каждой MV
  3. Таблицы будут атомарно обменены местами

Таким образом, в вашей таблице не будет пустых данных, пока MV пересоздаются.

-- models/events_daily.sql
{{
    config(
        materialized='table',
        engine='SummingMergeTree()',
        order_by='(event_date, event_type)',
        repopulate_from_mvs_on_full_refresh=True
    )
}}
...

Изменение целевой таблицы

Вы не можете изменить целевую таблицу MV без --full-refresh. Если после изменения ссылки materialization_target_table() попробовать выполнить обычную команду dbt run, сборка завершится ошибкой с сообщением о том, что целевая таблица была изменена.

Чтобы изменить целевую таблицу:

  1. Обновите вызов materialization_target_table()
  2. Выполните dbt run --full-refresh -s your_mv_model

Устранение типичных неполадок

Целевая таблица пуста во время или после выполнения run

Это может происходить по нескольким причинам:

  • Для materialized view может быть задано catchup=False, или для целевой таблицы может быть задано repopulate_from_mvs_on_full_refresh=False, поэтому при создании materialized views или пересоздании целевой таблицы дозагрузка не выполняется. Это ожидаемое поведение, поэтому, если вы хотите повторно вставить данные с помощью SQL materialized views, убедитесь, что для materialized view установлено catchup=True (это значение по умолчанию) или что для целевой таблицы задано repopulate_from_mvs_on_full_refresh=True. Не включайте оба параметра одновременно, чтобы избежать дубликатов. Подробнее см. в разделе конфигурации.
  • Во время выполнения dbt run --full-refresh, если materialized views используют значение по умолчанию catchup=True, целевая таблица будет пересоздана, а MV последовательно повторно вставят данные. Чтобы избежать этой ситуации, см. раздел Полное обновление с явными целевыми таблицами.

dbt run --full-refresh для целевой таблицы с repopulate_from_mvs_on_full_refresh=True использует логику из старых версий materialized view, а не из SQL, который сейчас находится в проекте

repopulate_from_mvs_on_full_refresh=True использует существующий SQL для MV, уже определённый в ClickHouse. Чтобы использовалось новое определение materialized view, выполните dbt run для каждой materialized view перед запуском dbt run --full-refresh для целевой таблицы.

После выполнения запуска появляются дубликаты данных

Возможные причины:

  • Одновременно могут быть включены и catchup=True для materialized view, и repopulate_from_mvs_on_full_refresh=True для целевой таблицы: оставьте только один из этих параметров в зависимости от того, какие операции вы хотите выполнять. Подробнее см. в разделе конфигурации.
  • Целевая таблица определена без WHERE 0: целевая таблица должна создаваться пустой, но внутренний запрос может вставить данные, если не указано WHERE 0. Убедитесь, что это условие добавлено.

Потеря данных во время активной ингестии после выполнения dbt run --full-refresh

Некоторые строки из исходной таблицы отсутствуют в целевой таблице после выполнения dbt run --full-refresh. materialized view в ClickHouse работают как триггеры вставки — они захватывают данные только пока существуют. Во время полного обновления возникает короткое окно, когда MV удаляется и создаётся заново («слепое окно»). Любые строки, вставленные в исходную таблицу в течение этого окна, не будут захвачены. Подробнее см. в разделе Поведение во время активной ингестии.

Методы отладки

Проверьте текущую целевую таблицу MV в ClickHouse

Выполните запрос к system.tables, чтобы посмотреть, в какую таблицу пишет materialized view:

SELECT
    name as mv_name,
    replaceRegexpOne(
        create_table_query,
        '.*TO\\s+`?([^`\\s(]+)`?\\.`?([^`\\s(]+)`?.*',
        '\\1.\\2'
    ) AS target_table
FROM system.tables
WHERE database = 'your_schema'
  AND engine = 'MaterializedView'

Проверьте, распознаёт ли dbt таблицу как целевую таблицу materialized view

Во время запуска dbt найдите в журнале следующее сообщение:

Таблица <table_name> используется как целевая таблица для materialized view, управляемого dbt. Чтобы предотвратить потерю данных, для mv_on_schema_change по умолчанию устанавливается значение "fail".

Если это сообщение появляется, значит dbt обнаружил, что таблица служит целевой как минимум для одного materialized view, управляемого dbt. Если вы ожидаете увидеть это сообщение, но его нет, проверьте следующее:

  • Модель materialized view корректно задаёт {{ materialization_target_table(ref('your_target')) }}
  • В config модели materialized view задано materialized='materialized_view'
  • И materialized view, и целевая таблица были выполнены как минимум один раз

Переход от неявной к явной целевой таблице

Если у вас уже есть модели materialized view, использующие подход с неявной целевой таблицей, и вы хотите перейти на подход с явной целевой таблицей, выполните следующие шаги:

1. Создайте модель целевой таблицы

Создайте новый файл модели с materialized='table', который определяет ту же схему, что и текущая целевая таблица MV. Используйте условие WHERE 0, чтобы создать пустую таблицу. Используйте то же имя, что и у текущей неявной модели materialized view. После этого вы сможете использовать эту модель для дальнейшей доработки целевой таблицы.

-- models/events_daily.sql
{{
    config(
        materialized='table',
        engine='MergeTree()',
        order_by='(event_date, event_type)'
    )
}}

SELECT
    toDate(now()) AS event_date,
    '' AS event_type,
    toUInt64(0) AS total
WHERE 0

2. Обновите модели MV

Создайте новые модели, каждая из которых должна включать SQL-код MV и вызов macro materialization_target_table(), указывающий на новую целевую таблицу. Если ранее вы использовали UNION ALL, удалите эту часть и комментарии.

Для имён моделей нужно придерживаться следующего соглашения об именовании:

  • если была определена только одна MV, она должна называться: <old_model_name>_mv
  • если было определено несколько MV, каждая должна называться: <old_model_name>_mv_<name_in_comments>

Ранее в my_model.sql (неявная целевая таблица, одна модель с UNION ALL):

--mv1:begin
select a, b, c from {{ source('raw', 'table_1') }}
--mv1:end
union all
--mv2:begin
select a, b, c from {{ source('raw', 'table_2') }}
--mv2:end

После (явная целевая таблица, отдельные файлы моделей):

-- models/my_model_mv_mv1.sql
{{ config(materialized='materialized_view') }}
{{ materialization_target_table(ref('events_daily')) }}

select a, b, c from {{ source('raw', 'table_1') }}
-- models/my_model_mv_mv2.sql
{{ config(materialized='materialized_view') }}
{{ materialization_target_table(ref('events_daily')) }}

select a, b, c from {{ source('raw', 'table_2') }}

3. При необходимости повторяйте эти действия, следуя инструкциям в разделе явная целевая таблица.

Сравнение поведения подходов с неявной и явной целевой таблицей

Общее поведение

Операция Неявная целевая таблица Явная целевая таблица
Первый запуск dbt Создаются все ресурсы Создаются все ресурсы
Следующий запуск dbt Отдельно управлять ресурсами нельзя — все происходит вместе:

целевая таблица:
изменения управляются настройкой on_schema_change. По умолчанию используется значение ignore, поэтому новые столбцы не обрабатываются.

Materialized views: все обновляются с помощью операций alter table modify query
Изменения можно применять по отдельности:

целевая таблица
:
автоматически определяется, является ли таблица целевой таблицей для materialized views, объявленных в dbt. Если да, то изменение столбцов по умолчанию управляется настройкой mv_on_schema_change со значением fail, поэтому при изменении столбцов выполнение завершится ошибкой. Мы добавили это значение по умолчанию как дополнительный защитный механизм

Materialized views: их SQL обновляется с помощью операций alter table modify query.
dbt run –full-refresh Отдельно управлять ресурсами нельзя — все происходит вместе:

целевая таблица
:
целевая таблица пересоздается пустой. Доступен параметр catchup для настройки дозагрузки с SQL всех materialized views сразу. По умолчанию catchup имеет значение True

Materialized views: все пересоздаются.
Изменения будут применяться по отдельности:

целевая таблица:
будет пересоздана как обычно.

Materialized views: удаляются и создаются заново. Для начальной дозагрузки доступен catchup. По умолчанию catchup имеет значение True.

Примечание: Во время этого процесса целевая таблица будет пустой или заполненной лишь частично, пока materialized views не будут пересозданы. Чтобы этого избежать, см. следующий раздел о том, как выполнять итерации целевой таблицы.

Поведение во время активной ингестии

При итерации над моделями важно учитывать, как разные операции взаимодействуют с вставляемыми данными:

  • Поскольку materialized view в ClickHouse работают как триггеры вставки, они захватывают данные только пока существуют. Если materialized view удаляется и создаётся заново (например, во время --full-refresh), любые строки, вставленные в исходную таблицу в этот промежуток, не будут обработаны materialized view. Это состояние называют «слепотой» materialized view.
  • Все процессы catchup основаны на операциях INSERT INTO ... SELECT, использующих SQL materialized view, и не зависят от того, как работают сами materialized view. После запуска INSERT новые данные в него уже не попадают, но будут захвачены присоединённой materialized view.

В следующей таблице приведено, насколько безопасна каждая операция, когда в исходную таблицу активно выполняются вставки.

Операции с неявной целевой таблицей

Операция Внутренний процесс Безопасность во время вставок
Первый dbt run 1. Создание целевой таблицы
2. Вставка данных (если catchup=True)
3. Создание materialized view
⚠️ materialized view не отслеживает данные между шагами 1 и 3. Любые строки, вставленные в источник в этот промежуток, не будут захвачены.
Последующий dbt run ALTER TABLE ... MODIFY QUERY ✅ Безопасно. materialized view обновляется атомарно.
dbt run --full-refresh 1. Создание резервной таблицы
2. Вставка данных (если catchup=True)
3. Удаление materialized view
4. Обмен таблиц
5. Повторное создание materialized view
⚠️ materialized view не отслеживает данные во время пересоздания. Данные, вставленные в источник между шагами 3 и 5, не появятся в новой целевой таблице.

Операции с явной целевой таблицей

Модели materialized view:

Операция Внутренний процесс Безопасность при выполняющихся вставках
Первый dbt run 1. Создание MV (с секцией TO)
2. Выполнение дозагрузки (если catchup=True)
✅ MV создаётся первой, поэтому новые вставки начинают захватываться сразу.
⚠️ Дозагрузка может привести к дублированию данных — запрос дозагрузки может пересекаться со строками, которые MV уже обрабатывает. Это безопасно при использовании движка с дедупликацией (например, ReplacingMergeTree).
Последующий dbt run ALTER TABLE ... MODIFY QUERY ✅ Безопасно. MV обновляется атомарно.
dbt run --full-refresh для MV 1. Удаление и повторное создание MV
2. Выполнение дозагрузки (если catchup=True)
⚠️ Во время пересоздания MV не видит новые данные (между удалением и созданием).
⚠️ Дозагрузка может привести к дублированию данных, если вставки идут параллельно.

Модель целевой таблицы:

Операция Внутренний процесс Безопасность при выполняющихся вставках
dbt run Изменения схемы применяются в соответствии с настройкой mv_on_schema_change ✅ Безопасно. Данные не перемещаются.
dbt run --full-refresh (по умолчанию) Повторное создание таблицы (она остаётся пустой) ⚠️ Целевая таблица пуста, пока MV не дозаполнят её. Как только новая таблица появляется, MV продолжают вставку в неё.
dbt run --full-refresh с repopulate_from_mvs_on_full_refresh=True 1. Создание резервной таблицы
2. Вставка данных с использованием SQL каждой MV
3. Атомарный обмен таблицами
⚠️ Во время пересоздания MV не видит данные. Данные, вставленные между шагами 1 и 3, не появятся в новой таблице. Это может измениться в следующих версиях.

Refreshable Materialized Views

Refreshable Materialized Views — это особый тип materialized view в ClickHouse, который периодически заново выполняет запрос и сохраняет результат — аналогично materialized view в других базах данных. Это полезно в сценариях, где нужны периодические снимки или агрегации, а не триггеры вставки в реальном времени.

Чтобы использовать refreshable materialized view, добавьте объект конфигурации refreshable в модель MV со следующими параметрами:

Параметр Описание Обязательно Значение по умолчанию
interval Предложение interval (обязательно), например EVERY 5 MINUTE Да
randomize Предложение рандомизации; указывается после RANDOMIZE FOR
append Если задано значение True, при каждом обновлении строки добавляются в таблицу без удаления существующих строк. Эта вставка не является атомарной, как и обычный INSERT SELECT. False
depends_on Список зависимостей для refreshable MV. Указывайте зависимости в следующем формате: {schema}.{view_name}
depends_on_validation Определяет, нужно ли проверять существование зависимостей, указанных в depends_on. Если для зависимости не указана схема, проверка выполняется в схеме default False

Пример с неявной целевой таблицей

{{
    config(
        materialized='materialized_view',
        engine='MergeTree()',
        order_by='(event_date)',
        refreshable={
            "interval": "EVERY 5 MINUTE",
            "randomize": "1 MINUTE",
            "append": True,
            "depends_on": ['schema.depend_on_model'],
            "depends_on_validation": True
        }
    )
}}

SELECT
    toStartOfDay(event_time) AS event_date,
    count() AS total
FROM {{ source('raw', 'events') }}
GROUP BY event_date

Пример с явной целевой таблицей

{{
    config(
        materialized='materialized_view',
        refreshable={
            "interval": "EVERY 1 HOUR",
            "append": False
        }
    )
}}
{{ materialization_target_table(ref('events_daily')) }}

SELECT
    toStartOfDay(event_time) AS event_date,
    event_type,
    count() AS total
FROM {{ source('raw', 'events') }}
GROUP BY event_date, event_type

Обновление параметров refresh

Начиная с dbt-clickhouse 1.10.2, параметры refresh (interval, randomize и depends_on) существующего refreshable materialized view можно изменять на месте при обычном запуске dbt run с помощью ALTER TABLE ... MODIFY REFRESH. Materialized view не удаляется и не создаётся заново, поэтому данные не теряются и во время применения изменений не возникает «слепого окна».

Некоторые изменения нельзя применить на месте. Вместо того чтобы молча их игнорировать, dbt завершит выполнение с ошибкой и предложит использовать dbt run --full-refresh:

  • Преобразование обычного materialized view в refreshable materialized view (добавление config refreshable) или наоборот (его удаление).
  • Изменение настройки append, поскольку ClickHouse не позволяет добавлять или удалять APPEND через MODIFY REFRESH.

Учтите, что --full-refresh удаляет и заново создаёт materialized view с последствиями, описанными в разделе Поведение при активной ингестии.

Ограничения

  • При создании в ClickHouse refreshable materialized view (MV) с зависимостью ClickHouse не генерирует ошибку, если указанная зависимость не существует на момент создания. Вместо этого refreshable MV остается в неактивном состоянии и ожидает, пока зависимость не будет удовлетворена, прежде чем начнет обрабатывать обновления или обновляться. Такое поведение является штатным, но оно может приводить к задержкам в доступности данных, если требуемая зависимость не будет своевременно создана. Перед созданием refreshable materialized view следует убедиться, что все зависимости корректно определены и существуют.
  • На данный момент фактическая «связь dbt» между mv и его зависимостями отсутствует, поэтому порядок создания не гарантируется.
  • Возможность refreshable не тестировалась для нескольких mv, направляющих данные в одну и ту же целевую модель.
Navigation