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

Обновляемый материализованный вид

Обновляемые материализованные представления концептуально схожи с материализованными представлениями в традиционных 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: