Перейти к основному содержанию
refreshable materialized views концептуально схожи с materialized view в традиционных OLTP-базах данных: они сохраняют результат указанного запроса для быстрого доступа и снижают необходимость многократно выполнять ресурсоемкие запросы. В отличие от incremental materialized view в ClickHouse, здесь запрос нужно периодически выполнять по всему набору данных, а его результаты сохраняются в целевой таблице для дальнейших запросов. Теоретически этот результирующий набор должен быть меньше исходного набора данных, что позволяет последующим запросам выполняться быстрее. На диаграмме показано, как работают Refreshable Materialized Views: Вы также можете посмотреть следующее видео:

Когда следует использовать refreshable materialized views?

ClickHouse incremental materialized views чрезвычайно эффективны и, как правило, масштабируются значительно лучше, чем подход с refreshable materialized views, особенно когда требуется выполнить агрегацию по одной таблице. Поскольку агрегация вычисляется только для каждого блока данных по мере его вставки, а инкрементальные состояния затем сливаются в итоговой таблице, запрос всегда выполняется лишь на подмножестве данных. Этот метод может масштабироваться до PB данных и обычно является предпочтительным. Однако есть сценарии, в которых этот инкрементальный процесс не нужен или неприменим. Некоторые задачи либо несовместимы с инкрементальным подходом, либо не требуют обновлений в реальном времени, и в таких случаях более уместно периодическое полное перестроение. Например, может потребоваться регулярно полностью пересчитывать представление по всему набору данных, если в нем используется сложный JOIN, несовместимый с инкрементальным подходом.
Refreshable materialized views могут запускать батч-процессы и выполнять такие задачи, как денормализация. Между refreshable materialized views можно задавать зависимости, чтобы одно представление зависело от результатов другого и выполнялось только после его завершения. Это может заменить запланированные рабочие процессы или простые DAG, например задачу dbt. Подробнее о том, как задавать зависимости между refreshable materialized views, см. в разделе Dependencies страницы CREATE VIEW.

Как обновить refreshable materialized view?

Refreshable materialized views автоматически обновляются с интервалом, который задаётся при создании. Например, materialized view ниже обновляется каждую минуту:
Если вы хотите принудительно обновить materialized view, можно использовать команду SYSTEM REFRESH VIEW:
Вы также можете отменить, остановить или запустить refreshable materialized view. Подробнее см. в документации по управлению refreshable materialized views.

Когда в последний раз обновлялась refreshable materialized view?

Чтобы узнать, когда refreshable materialized view обновлялась в последний раз, вы можете выполнить запрос к системной таблице system.view_refreshes, как показано ниже:

Как изменить частоту обновления?

Чтобы изменить частоту обновления refreshable materialized view, используйте синтаксис ALTER TABLE...MODIFY REFRESH.
После этого вы можете воспользоваться запросом Когда refreshable materialized view обновлялось в последний раз?, чтобы проверить, что значение rate было обновлено:

Использование APPEND для добавления новых строк

Функция APPEND позволяет добавлять новые строки в конец таблицы, не заменяя представление целиком. Один из вариантов использования этой возможности — фиксировать снимки значений на определённый момент времени. Например, представим, что у нас есть таблица events, заполняемая потоком сообщений из Kafka, Redpanda или другой стриминговой платформы данных.
Этот набор данных содержит 4096 значений в столбце uuid. Мы можем выполнить следующий запрос, чтобы найти значения с наибольшим общим количеством вхождений:
Допустим, мы хотим каждые 10 секунд сохранять количество для каждого uuid в новой таблице events_snapshot. Схема events_snapshot будет выглядеть так:
Затем мы можем создать refreshable materialized view, чтобы заполнить эту таблицу:
Затем мы можем выполнить запрос к events_snapshot, чтобы получить количество для конкретного uuid в динамике:

Примеры

Теперь рассмотрим, как использовать refreshable materialized views на примере нескольких наборов данных.

Stack Overflow

В руководстве по денормализации данных показаны различные методы денормализации данных на примере набора данных Stack Overflow. Мы загружаем данные в следующие таблицы: votes, users, badges, posts и postlinks. В этом руководстве мы показали, как денормализовать набор данных postlinks в таблицу posts с помощью следующего запроса:
Затем мы показали, как выполнить разовую вставку этих данных в таблицу posts_with_links, но в производственной системе эту операцию нужно запускать периодически. Обновляться потенциально могут обе таблицы: posts и postlinks. Поэтому вместо того, чтобы пытаться реализовать этот JOIN с помощью incremental materialized views, может быть достаточно просто запускать этот запрос через заданные интервалы, например раз в час, сохраняя результаты в таблице post_with_links. Здесь как раз полезна refreshable materialized view, и создать её можно с помощью следующего запроса:
Представление будет выполнено немедленно, а затем — каждый час в соответствии с настройкой, чтобы изменения в исходной таблице отражались в нём. Важно, что при повторном выполнении запроса результирующий набор обновляется атомарно и прозрачно.
Синтаксис здесь идентичен incremental materialized view, за исключением того, что мы добавляем предложение REFRESH:

IMDb

В руководстве по интеграции dbt и ClickHouse мы заполнили набор данных IMDb следующими таблицами: actors, directors, genres, movie_directors, movies и roles. Затем можно написать следующий запрос, чтобы получить сводную информацию по каждому актёру, упорядоченную по числу появлений в фильмах.
Получение результата занимает не так много времени, но предположим, что мы хотим сделать его ещё быстрее и снизить вычислительные затраты. Предположим также, что этот набор данных постоянно обновляется: выходят новые фильмы, появляются новые актёры и режиссёры. Теперь пригодится refreshable materialized view, поэтому сначала создадим целевую таблицу для результатов:
Теперь можно определить представление:
Представление будет выполнено немедленно, а затем — каждую минуту, как задано в настройках, чтобы в нём отражались обновления исходной таблицы. Наш предыдущий запрос для получения сводки по актёрам становится синтаксически проще и работает значительно быстрее!
Допустим, мы добавим в исходные данные нового актёра — “Clicky McClickHouse”, который снялся во множестве фильмов!
Менее чем через 60 секунд наша целевая таблица обновится, отразив впечатляюще плодотворную актёрскую карьеру Clicky:
Последнее изменение 10 июня 2026 г.