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

Обновляемое материализованное представление

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