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

Вы также можете посмотреть следующее видео:
Когда следует использовать обновляемые материализованные представления?
Инкрементные материализованные представления ClickHouse обладаются огромной мощностью и, как правило, масштабируются намного лучше, чем подход, используемый обновляемыми материализованными представлениями, особенно в случаях, когда необходимо провести агрегацию над одной таблицей. Путем выполнения агрегации только на каждом блоке данных по мере его вставки и слияния инкрементных состояний в окончательной таблице, запрос выполняется только на подмножестве данных. Этот метод может масштабироваться до потенциальных петабайт данных и, как правило, является предпочтительным методом.
Тем не менее, существуют случаи использования, в которых этот инкрементный процесс не требуется или не применим. Некоторые задачи несовместимы с инкрементным подходом или не требуют обновлений в реальном времени, при этом периодическое восстановление будет более уместным. Например, вы можете периодически выполнять полное пересчитывание представления по полному набору данных, потому что оно использует сложное соединение, что несовместимо с инкрементным подходом.
Обновляемые материализованные представления могут выполнять пакетные процессы, выполняя такие задачи, как денормализация. Можно создать зависимости между обновляемыми материализованными представлениями, при этом одно представление зависит от результатов другого и выполняется только после его завершения. Это может заменить запланированные рабочие процессы или простые DAG, такие как dbt. Чтобы узнать больше о том, как установить зависимости между обновляемыми материализованными представлениями, перейдите в раздел СОЗДАТЬ ПРЕДСТАВЛЕНИЕ, раздел
Зависимости
.
Как обновить обновляемое материализованное представление?
Обновляемые материализованные представления автоматически обновляются с интервалом, определенным во время создания. Например, следующее материализованное представление обновляется каждую минуту:
Если нужно принудительно обновить материализованное представление, вы можете использовать конструкцию 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: