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

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

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