Обновляемый материализованный вид
Обновляемые материализованные представления концептуально схожи с материализованными представлениями в традиционных OLTP базах данных, они хранят результат заданного запроса для быстрого извлечения и уменьшают необходимость многократного выполнения ресурсоемких запросов. В отличие от инкрементальных материализованных представлений ClickHouse, это требует периодического выполнения запроса по всему набору данных, результаты чего хранятся в целевой таблице для запросов. Этот набор результатов, в теории, должен быть меньше оригинального набора данных, что позволяет последующему запросу выполняться быстрее.
Диаграмма объясняет, как работают обновляемые материализованные представления:

Вы также можете посмотреть следующее видео:
Когда следует использовать обновляемые материализованные представления?
Инкрементальные материализованные представления ClickHouse невероятно мощные и обычно масштабируются гораздо лучше, чем подход, используемый обновляемыми материализованными представлениями, особенно в случаях, когда необходимо выполнить агрегирование по одной таблице. Поскольку агрегирование вычисляется только по каждому блоку данных по мере ввода и инкрементальные состояния объединяются в окончательной таблице, запрос выполняется только на подмножестве данных. Этот метод может масштабироваться до потенциальных петабайтов данных и обычно является предпочтительным.
Тем не менее, есть случаи, когда этот инкрементальный процесс не требуется или не применим. Некоторые задачи либо несовместимы с инкрементальным подходом, либо не требуют обновлений в реальном времени, и периодическая пересборка будет более уместной. Например, вы можете хотеть регулярно выполнять полное пересчисление представления по всему набору данных, потому что оно использует сложное соединение, что несовместимо с инкрементальным подходом.
Обновляемые материализованные представления могут выполнять пакетные процессы, осуществляя такие задачи, как денормализация. Между обновляемыми материализованными представлениями могут быть созданы зависимости, так что одно представление зависит от результатов другого и выполняется только после его завершения. Это может заменить запланированные рабочие процессы или простые DAG, такие как dbt задача. Чтобы узнать больше о том, как установить зависимости между обновляемыми материализованными представлениями, перейдите в раздел CREATE VIEW, раздел
Dependencies
.
Как обновить обновляемое материализованное представление?
Обновляемые материализованные представления обновляются автоматически с интервалом, который определяется при создании. Например, следующее материализованное представление обновляется каждую минуту:
Если вы хотите принудительно обновить материализованное представление, вы можете использовать оператор SYSTEM REFRESH VIEW
:
Вы также можете отменить, остановить или запустить представление. Для получения более подробной информации смотрите документацию по управлению обновляемыми материализованными представлениями.
Когда в последний раз обновлялось обновляемое материализованное представление?
Чтобы узнать, когда последнее обновлялось обновляемое материализованное представление, вы можете выполнить запрос к системной таблице system.view_refreshes
, как показано ниже:
Как изменить частоту обновления?
Чтобы изменить частоту обновления обновляемого материализованного представления, используйте синтаксис ALTER TABLE...MODIFY REFRESH
.
После этого вы можете использовать запрос Когда в последний раз обновлялось обновляемое материализованное представление?, чтобы проверить, что частота обновления была изменена:
Использование APPEND
для добавления новых строк
Функция APPEND
позволяет вам добавлять новые строки в конец таблицы, а не заменять все представление.
Одно из применений этой функции — захват снимков значений в определенный момент времени. Например, представим, что у нас есть таблица events
, заполняемая потоком сообщений из Kafka, Redpanda, или другой платформы потоковых данных.
Этот набор данных содержит 4096
значений в колонке uuid
. Мы можем написать следующий запрос, чтобы найти значения с наибольшим общим количеством:
Предположим, что мы хотим захватить количество для каждого uuid
каждые 10 секунд и сохранить это в новой таблице под названием events_snapshot
. Схема events_snapshot
будет выглядеть так:
Затем мы можем создать обновляемое материализованное представление для заполнения этой таблицы:
Затем мы можем выполнить запрос к events_snapshot
, чтобы получить количество по времени для конкретного uuid
:
Примеры
Теперь давайте рассмотрим, как использовать обновляемые материализованные представления с некоторыми примерами наборов данных.
Stack Overflow
Руководство по денормализации данных демонстрирует различные техники денормализации данных с использованием набора данных Stack Overflow. Мы заполняем данные в следующие таблицы: votes
, users
, badges
, posts
, и postlinks
.
В этом руководстве мы показали, как денормализовать набор данных postlinks
в таблицу posts
с помощью следующего запроса:
Затем мы показали, как разово вставить эти данные в таблицу posts_with_links
, но в производственной системе мы бы хотели выполнять эту операцию периодически.
И таблицы posts
, и postlinks
могут быть потенциально обновлены. Поэтому, вместо того чтобы пытаться реализовать это соединение с помощью инкрементальных материализованных представлений, может быть достаточно просто запланировать этот запрос на выполнение с установленным интервалом, например, один раз в час, сохраняя результаты в таблице post_with_links
.
Здесь обновляемое материализованное представление поможет, и мы можем создать одно с помощью следующего запроса:
Представление будет выполняться немедленно и каждый час после этого, как настроено, чтобы гарантировать отражение обновлений в исходной таблице. Важно, что когда запрос повторно выполняется, набор результатов атомарно и прозрачно обновляется.
Синтаксис здесь идентичен инкрементальному материализованному представлению, за исключением того, что мы включаем REFRESH
клаузу:
IMDb
В руководстве по интеграции dbt и ClickHouse мы заполнили набор данных IMDb следующими таблицами: actors
, directors
, genres
, movie_directors
, movies
, и roles
.
Затем мы можем написать следующий запрос, который можно использовать для вычисления сводки для каждого актера, упорядоченной по количеству появлений в фильмах:
Не требуется много времени для получения результата, но давайте скажем, что мы хотим, чтобы это было еще быстрее и менее трудоемким с точки зрения вычислений. Предположим, что этот набор данных также подвержен постоянным обновлениям — фильмы постоянно выпускаются, новые актеры и режиссеры также появляются.
Пришло время для обновляемого материализованного представления, так что сначала создадим целевую таблицу для результатов:
А теперь мы можем определить представление:
Представление будет выполняться немедленно и каждую минуту после этого, как настроено, чтобы гарантировать отражение обновлений в исходной таблице. Наш предыдущий запрос для получения сводки актеров становится синтаксически проще и значительно быстрее!
Предположим, мы добавим нового актера, "Clicky McClickHouse", в наши исходные данные, который, кстати, появился во множестве фильмов!
Менее чем через 60 секунд наша целевая таблица обновляется, чтобы отразить плодовитую природу актёрской деятельности Clicky: