Каскадные материализованные представления
В этом примере демонстрируется, как создать материализованное представление, а затем как каскадировать второе материализованное представление на первое. На этой странице вы увидите, как это сделать, многие возможности и ограничения. Разные случаи использования могут быть решены созданием материализованного представления с использованием второго материализованного представления в качестве источника.
Пример:
Мы будем использовать фейковый набор данных с количеством просмотров в час для группы доменных имен.
Наша цель
- Нам нужны данные, агрегированные по месяцам для каждого доменного имени,
- Нам также нужны данные, агрегированные по годам для каждого доменного имени.
Вы можете выбрать один из этих вариантов:
- Написать запросы, которые будут читать и агрегировать данные во время выполнения запроса SELECT
- Подготовить данные во время их поступления к новому формату
- Подготовить данные во время поступления к конкретной агрегации.
Подготовка данных с использованием материализованных представлений позволит вам ограничить количество данных и вычислений, которые необходимо выполнить ClickHouse, что сделает ваши запросы SELECT быстрее.
Исходная таблица для материализованных представлений
Создайте исходную таблицу, так как наши цели связаны с отчетностью по агрегированным данным, а не по отдельным строкам, мы можем разобрать данные, передать информацию в материализованные представления и отбросить фактически поступающие данные. Это соответствует нашим целям и экономит место для хранения, поэтому мы будем использовать движок таблицы Null
.
Вы можете создать материализованное представление на таблице Null. Таким образом, данные, записанные в таблицу, в конечном итоге повлияют на представление, но оригинальные необработанные данные все равно будут отброшены.
Ежемесячная агрегированная таблица и материализованное представление
Для первого материализованного представления нам нужно создать целевую таблицу, для этого примера она будет analytics.monthly_aggregated_data
, и мы будем хранить сумму просмотров по месяцам и доменным именам.
Материализованное представление, которое будет передавать данные в целевую таблицу, будет выглядеть следующим образом:
Ежегодная агрегированная таблица и материализованное представление
Теперь мы создадим второе материализованное представление, которое будет связано с нашей предыдущей целевой таблицей monthly_aggregated_data
.
Сначала мы создадим новую целевую таблицу, которая будет хранить сумму просмотров, агрегированных по годам для каждого доменного имени.
Этот шаг определяет каскад. Оператор FROM
будет использовать таблицу monthly_aggregated_data
, это значит, что поток данных будет следующим:
- Данные поступают в таблицу
hourly_data
. - ClickHouse передаст полученные данные в первое материализованное представление
monthly_aggregated_data
, - Наконец, данные, полученные на шаге 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
.
Сначала создайте две исходные таблицы, представляющие разные наборы метрик:
Затем создайте целевую таблицу с объединенным набором метрик:
Создайте два материализованных представления, указывающих на одну и ту же целевую таблицу. Вам не нужно явно включать отсутствующие столбцы:
Теперь, когда вы вставляете значения, эти значения будут агрегироваться в соответствующие столбцы целевой таблицы:
Объединенные просмотры и клики в целевой таблице:
Этот запрос должен вернуть что-то вроде: