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

Каскадные материализованные представления

В этом примере демонстрируется, как создать материализованное представление, а затем как каскадировать второе материализованное представление на первое. На этой странице вы увидите, как это сделать, многие возможности и ограничения. Разные случаи использования могут быть решены созданием материализованного представления с использованием второго материализованного представления в качестве источника.


Пример:

Мы будем использовать фейковый набор данных с количеством просмотров в час для группы доменных имен.

Наша цель

  1. Нам нужны данные, агрегированные по месяцам для каждого доменного имени,
  2. Нам также нужны данные, агрегированные по годам для каждого доменного имени.

Вы можете выбрать один из этих вариантов:

  • Написать запросы, которые будут читать и агрегировать данные во время выполнения запроса SELECT
  • Подготовить данные во время их поступления к новому формату
  • Подготовить данные во время поступления к конкретной агрегации.

Подготовка данных с использованием материализованных представлений позволит вам ограничить количество данных и вычислений, которые необходимо выполнить ClickHouse, что сделает ваши запросы SELECT быстрее.

Исходная таблица для материализованных представлений

Создайте исходную таблицу, так как наши цели связаны с отчетностью по агрегированным данным, а не по отдельным строкам, мы можем разобрать данные, передать информацию в материализованные представления и отбросить фактически поступающие данные. Это соответствует нашим целям и экономит место для хранения, поэтому мы будем использовать движок таблицы Null.

примечание

Вы можете создать материализованное представление на таблице Null. Таким образом, данные, записанные в таблицу, в конечном итоге повлияют на представление, но оригинальные необработанные данные все равно будут отброшены.

Ежемесячная агрегированная таблица и материализованное представление

Для первого материализованного представления нам нужно создать целевую таблицу, для этого примера она будет analytics.monthly_aggregated_data, и мы будем хранить сумму просмотров по месяцам и доменным именам.

Материализованное представление, которое будет передавать данные в целевую таблицу, будет выглядеть следующим образом:

Ежегодная агрегированная таблица и материализованное представление

Теперь мы создадим второе материализованное представление, которое будет связано с нашей предыдущей целевой таблицей monthly_aggregated_data.

Сначала мы создадим новую целевую таблицу, которая будет хранить сумму просмотров, агрегированных по годам для каждого доменного имени.

Этот шаг определяет каскад. Оператор FROM будет использовать таблицу monthly_aggregated_data, это значит, что поток данных будет следующим:

  1. Данные поступают в таблицу hourly_data.
  2. ClickHouse передаст полученные данные в первое материализованное представление monthly_aggregated_data,
  3. Наконец, данные, полученные на шаге 2, будут переданы в year_aggregated_data.
примечание

Общее неверное толкование при работе с материализованными представлениями заключается в том, что данные читает таблица. Это не то, как работают материализованные представления; переданные данные — это вставленный блок, а не конечный результат в вашей таблице.

Предположим, в этом примере движок, используемый в monthly_aggregated_data, это CollapsingMergeTree, переданные данные в наше второе материализованное представление year_aggregated_data_mv не будут конечным результатом свернутой таблицы, это будет блок данных с полями, определенными в SELECT ... GROUP BY.

Если вы используете CollapsingMergeTree, ReplacingMergeTree или даже SummingMergeTree и планируете создать каскадное материализованное представление, вам нужно понять ограничения, описанные здесь.

Пример данных

Теперь пришло время протестировать наше каскадное материализованное представление, вставив некоторые данные:

Если вы выполните запрос на выборку содержимого analytics.hourly_data, вы увидите следующее, поскольку движок таблицы — Null, но данные были обработаны.

Мы использовали небольшой набор данных, чтобы убедиться, что можем следить и сравнивать результаты с тем, что мы ожидаем, когда ваш поток корректен с небольшим набором данных, вы можете просто перейти к большому объему данных.

Результаты

Если вы попытаетесь выполнить запрос к целевой таблице, выбрав поле sumCountViews, вы увидите двоичное представление (в некоторых терминалах), так как значение не хранится как число, а как тип AggregateFunction. Чтобы получить конечный результат агрегации, вы должны использовать суффикс -Merge.

Вы можете увидеть специальные символы, сохраненные в AggregateFunction, с помощью этого запроса:

Вместо этого давайте попробуем использовать суффикс Merge, чтобы получить значение sumCountViews:

В AggregatingMergeTree мы определили AggregateFunction как sum, поэтому мы можем использовать sumMerge. Когда мы используем функцию avg на AggregateFunction, мы будем использовать avgMerge и так далее.

Теперь мы можем проверить, что материализованные представления отвечают нашей цели.

Теперь, когда мы сохранили данные в целевой таблице monthly_aggregated_data, мы можем получить данные, агрегированные по месяцам для каждого доменного имени:

Данные, агрегированные по годам для каждого доменного имени:

Объединение нескольких исходных таблиц в одну целевую таблицу

Материализованные представления также могут использоваться для объединения нескольких исходных таблиц в одну целевую таблицу. Это полезно для создания материализованного представления, которое аналогично логике UNION ALL.

Сначала создайте две исходные таблицы, представляющие разные наборы метрик:

Затем создайте целевую таблицу с объединенным набором метрик:

Создайте два материализованных представления, указывающих на одну и ту же целевую таблицу. Вам не нужно явно включать отсутствующие столбцы:

Теперь, когда вы вставляете значения, эти значения будут агрегироваться в соответствующие столбцы целевой таблицы:

Объединенные просмотры и клики в целевой таблице:

Этот запрос должен вернуть что-то вроде: