Введение
Оповещения тоже могут выигрывать от materialized views и будут использовать их автоматически.
Это может снизить вычислительные затраты на выполнение большого количества оповещений, особенно потому, что они обычно запускаются очень часто.
Сокращение времени выполнения положительно сказывается и на отзывчивости, и на потреблении ресурсов.
Что такое incremental materialized views
SELECT.
В отличие от транзакционных баз данных, таких как Postgres, materialized view в ClickHouse — это не сохранённый снимок. Вместо этого она работает как trigger, который выполняет запрос над блоками данных по мере их вставки в исходную таблицу. Результат этого запроса записывается в отдельную целевую таблицу. По мере вставки новых данных в целевую таблицу добавляются новые частичные результаты, которые затем сливаются. Итоговый слитый результат эквивалентен выполнению агрегации по всему исходному набору данных.
Основная причина использовать materialized views заключается в том, что данные, записываемые в целевую таблицу, представляют собой результат агрегации, фильтрации или преобразования. В ClickStack они используются исключительно для агрегаций. Эти результаты обычно значительно меньше, чем исходные данные, и часто представляют собой Промежуточные состояния агрегации. В сочетании с простотой запросов к предварительно агрегированной целевой таблице это даёт существенно меньшую задержку по сравнению с выполнением тех же вычислений над сырыми данными во время выполнения запроса.
Materialized views в ClickHouse непрерывно обновляются по мере поступления данных в исходную таблицу и больше похожи на всегда актуальные индексы. Это отличается от многих других баз данных, где materialized views представляют собой статические снимки, которые нужно периодически обновлять, как в ClickHouse Refreshable Materialized Views.
Incremental materialized views вычисляют только изменения в представлении по мере поступления новых данных, перенося вычисления на момент вставки. Поскольку ClickHouse хорошо оптимизирован для ингестии, дополнительные затраты на поддержку представления для каждого вставленного блока невелики по сравнению с выигрышем при выполнении запросов. Стоимость вычисления агрегации распределяется между операциями вставки, а не оплачивается заново при каждом чтении. Поэтому запросы к предварительно агрегированным результатам обходятся значительно дешевле, чем их повторное вычисление, что снижает эксплуатационные затраты и обеспечивает производительность, близкую к реальному времени, для последующих визуализаций даже в масштабе петабайтов.
Эта модель принципиально отличается от систем, которые пересчитывают представления целиком при каждом обновлении или полагаются на обновление по расписанию. Более подробное объяснение того, как работают materialized views и как их создавать, см. в руководстве по ссылке выше.
Каждое materialized view создаёт дополнительную нагрузку в момент вставки, поэтому их следует использовать выборочно.
Одно materialized view может вычислять несколько метрик для разных группировок, например минимальную, максимальную и p95 длительность для каждого service name в одноминутных бакетах. Это позволяет одному представлению использоваться во множестве визуализаций, а не только в одной. Поэтому важно объединять метрики в общие представления, чтобы максимально повысить ценность каждого представления и обеспечить его повторное использование в панелях мониторинга и рабочих процессах.
Выбор визуализаций для ускорения
Определите визуализации, где ускорение даст наибольший эффект
- Визуализации на панелях мониторинга, которые часто обновляются и постоянно отображаются, например сводные панели мониторинга на настенных экранах.
- Диагностические сценарии из runbook, в которых во время реагирования на инциденты к определённым диаграммам обращаются repeatedly и результаты должны возвращаться быстро.
- Ключевые сценарии работы в HyperDX, включая:
- Представления гистограмм на странице Search.
- Визуализации, используемые в предустановленных панелях мониторинга, таких как APM, Services или Kubernetes.
Соизмеряйте пользу с затратами при вставке
Перед переходом в продакшн всегда проверяйте дополнительную нагрузку на ресурсы, создаваемую materialized view, особенно загрузку CPU, дисковый I/O и активность слияния. Каждая materialized view увеличивает объём работы при вставке и добавляет новые части, поэтому важно убедиться, что слияния успевают за нагрузкой, а число частей остаётся стабильным. Это можно отслеживать через системные таблицы и встроенную панель мониторинга обсервабилити в open-source ClickHouse или с помощью встроенных метрик и панелей мониторинга в ClickHouse Cloud. Рекомендации по диагностике и устранению чрезмерного числа частей см. в разделе Too many parts.
toStartOfMinute. Однако многие визуализации также используют дополнительные ключи группировки, например имя сервиса, имя спана или код статуса. Если несколько визуализаций используют одни и те же измерения для группировки, их часто можно обслужить с помощью одной materialized view.
Например (для трассировок):
- Средняя длительность по имени сервиса с разбивкой по времени -
SELECT avg(Duration), toStartOfMinute(Timestamp) as time, ServiceName FROM otel_traces GROUP BY ServiceName, time - Количество запросов по имени сервиса с разбивкой по времени -
SELECT count() count, toStartOfMinute(Timestamp) as time, ServiceName FROM otel_traces GROUP BY ServiceName, time - Средняя длительность по коду статуса с разбивкой по времени -
SELECT avg(Duration), toStartOfMinute(Timestamp) as time, StatusCode FROM otel_traces GROUP BY StatusCode, time - Количество запросов по коду статуса с разбивкой по времени -
SELECT count() count, toStartOfMinute(Timestamp) as time, StatusCode FROM otel_traces GROUP BY StatusCode, time
Создание materialized view
Если в HyperDX для компонента недоступна панель отладки, пользователи могут проверить консоль браузера, где записываются все запросы.
AggregatingMergeTree:
Ниже вы можете посмотреть пример использования AggregatingMergeTree и агрегатных функций:
Пример materialized view
otel_traces_1m, в которой будут храниться соответствующие состояния агрегирования:
otel_traces_1m_mv — затем вычисляет и записывает эти состояния при вставке новых данных:
- Целевая таблица, которая определяет схему и типы агрегатных состояний, используемые для хранения промежуточных результатов. Чтобы эти состояния корректно объединялись в фоне, требуется движок AggregatingMergeTree.
- Запрос materialized view автоматически выполняется при вставке. По сравнению с исходным запросом он использует функции состояний, такие как
avgStateиquantilesState, вместо финальных агрегатных функций.
Использование materialized view в ClickStack
Регистрация materialized view для использования
Измените источник
Перейдите к нужному источнику в HyperDX и откройте диалог Edit configuration. Прокрутите страницу до раздела materialized views.Добавьте materialized view
Выберите Add materialized view, затем укажите базу данных и целевую таблицу, на которых основано materialized view.Выберите метрики
В большинстве случаев столбцы временной метки, размерности и метрик будут определены автоматически. Если этого не произошло, укажите их вручную.Для метрик необходимо сопоставить:- исходное имя столбца, например
Duration, с - соответствующим агрегированным столбцом в materialized view, например
avg__Duration
Выберите временную гранулярность
Выберите временную гранулярность materialized view, например одну минуту.Выберите минимальную дату
Укажите минимальную дату, начиная с которой materialized view содержит данные. Это самая ранняя временная метка, доступная в представлении, и обычно это время создания представления, если ингестия шла непрерывно.materialized view не дозагружаются автоматически при создании, поэтому они будут содержать только строки, сформированные из данных, вставленных после создания.
Полное руководство по дозагрузке materialized views можно найти в разделе “Дозагрузка данных.”
Сохраните источник
Сохраните конфигурацию источника.Проверка ускорения в панелях мониторинга и визуализациях
ClickStack будет использовать materialized view, только если её минимальная временная метка меньше или равна началу временного диапазона запроса — это гарантирует, что представление содержит все необходимые данные. Хотя запросы внутри системы разбиваются на подзапросы по времени, materialized view применяются либо ко всему запросу целиком, либо не применяются вовсе. В будущем возможны улучшения, которые позволят использовать представления выборочно для подходящих подзапросов.
- Проверьте статус оптимизации При просмотре панели мониторинга или визуализации найдите значок молнии или
Accelerated:
- Зелёная молния означает, что запрос ускорен с помощью materialized view.
- Оранжевая молния означает, что запрос выполняется по исходной таблице.
- Изучите сведения об оптимизации Нажмите на значок молнии, чтобы открыть панель с подробностями, где показано:
- Активное materialized view: представление, выбранное для запроса, включая оценочное количество строк.
- Пропущенные materialized view: совместимые представления, которые не были выбраны, вместе с оценочным объёмом сканирования.
- Несовместимые materialized view: представления, которые не удалось использовать, и конкретная причина.
- Разберитесь в распространённых причинах несовместимости Materialized view может не использоваться, если:
- Временной диапазон запроса начинается раньше минимальной временной метки представления.
- Гранулярность визуализации не кратна гранулярности представления.
- Функция агрегации, запрошенная в запросе, отсутствует в представлении.
- В запросе используются пользовательские выражения count, например
count(if(...)), которые нельзя получить из состояний агрегации представления.
Как materialized views выбираются для визуализаций
EXPLAIN ESTIMATE.
Процесс выбора проходит по четко определенной последовательности:
-
Проверка совместимости
Сначала ClickStack определяет, подходит ли materialized view для запроса, проверяя:
- Покрытие по времени: временной диапазон запроса должен полностью попадать в доступный диапазон данных materialized view.
- Гранулярность: временной бакет визуализации должен быть равен гранулярности view или быть более грубым.
- Агрегации: запрошенные метрики должны присутствовать во view и вычисляться из их состояний агрегации.
-
Преобразование запроса
Для совместимых view ClickStack переписывает запрос так, чтобы он обращался к таблице materialized view:
- Функции агрегации сопоставляются с соответствующими материализованными столбцами.
- К состояниям агрегации применяются комбинаторы
-Merge. - Группировка по времени корректируется в соответствии с гранулярностью view.
-
Выбор лучшего кандидата
Если доступно несколько совместимых materialized views, ClickStack выполняет запрос
EXPLAIN ESTIMATEдля каждого кандидата и сравнивает расчетное число просканированных строк и гранул. Выбирается view с наименьшей расчетной стоимостью сканирования. - Плавный fallback Если ни один materialized view не подходит, ClickStack автоматически возвращается к запросу исходной таблицы.
Пример выбора materialized views
otel_traces_1m, сгруппированное по минутам,ServiceNameиStatusCodeotel_traces_1m_v2, сгруппированное по минутам,ServiceName,StatusCodeиSpanName
EXPLAIN ESTIMATE для каждого кандидата и сравнивает оценочное количество гранул, то есть:
otel_traces_1m меньше и сканирует меньше гранул, она выбирается автоматически.
Обе materialized view по-прежнему работают быстрее, чем запросы напрямую к базовой таблице, но выбор наименьшего подходящего представления обеспечивает наилучшую производительность.
Оповещения
Дозагрузка materialized view
Подходы к дозагрузке
Избегайте POPULATEИспользовать команду POPULATE для дозагрузки materialized view не рекомендуется, за исключением небольших наборов данных, когда приём приостановлен. Этот оператор может пропускать строки, вставленные в исходную таблицу, поскольку materialized view создаётся только после завершения POPULATE. Кроме того, POPULATE выполняется по всем данным и на больших наборах данных подвержен сбоям из-за прерываний или ограничений памяти.
Прямая дозагрузка с помощью INSERT INTO SELECT
Определите текущее покрытие представления
Прежде чем выполнять дозагрузку, сначала определите, какие данные уже содержит materialized view. Для этого выполните запрос, возвращающий минимальную временную метку в целевой таблице:Решите, нужна ли дозагрузка
В большинстве развертываний ClickStack запросы сосредоточены на недавних данных, например за последние 24 часа. В таких случаях вновь созданные представления становятся полностью пригодными к использованию вскоре после создания, и дозагрузка не требуется.Если временная метка, полученная на предыдущем шаге, достаточно ранняя для ваших сценариев использования, дозагрузка не нужна. Рассматривать дозагрузку следует только в следующих случаях:- Запросы часто охватывают длинные исторические диапазоны.
- Представление критично для производительности на этих диапазонах.
- Размер набора данных и стоимость агрегации делают дозагрузку целесообразной.
Дозагрузите отсутствующие исторические данные
Если дозагрузка необходима, заполните целевую таблицу materialized view для временных меток раньше текущего минимума, используя запрос из представления, изменённый так, чтобы он читал только данные старше временной метки, зафиксированной выше. Поскольку целевая таблица использует AggregatingMergeTree, запрос дозагрузки должен вставлять состояния агрегации, а не итоговые значения.Обратите внимание, что следующий запрос добавляет условиеWHERE, чтобы ограничить агрегацию данными старше самой ранней временной метки, присутствующей в представлении:Инкрементальная дозагрузка с использованием таблицы Null
INSERT INTO SELECT может быть непрактичной или небезопасной. В таких случаях рекомендуется подход инкрементальной дозагрузки. Этот метод точнее воспроизводит обычную работу incremental materialized views: данные обрабатываются управляемыми блоками, а не агрегируются сразу по всему историческому набору данных.
Этот подход подходит, когда:
- Иначе запрос дозагрузки выполнялся бы много часов.
- Пиковое потребление памяти при полной агрегации слишком велико.
- Вы хотите жёстко контролировать потребление CPU и памяти во время дозагрузки.
- Вам нужен более устойчивый процесс, который можно безопасно перезапустить в случае прерывания.
Создайте таблицу Null для дозагрузки
Создайте лёгкую таблицу Null, содержащую только те столбцы, которые нужны для агрегации в materialized view. Это минимизирует I/O и использование памяти.Прикрепите materialized view к таблице Null
Затем создайте materialized view для таблицы Null, направленную в ту же таблицу агрегации, что и ваша основная materialized view.Выполните инкрементальную дозагрузку данных
Наконец, вставьте исторические данные в таблицу Null. Materialized view будет обрабатывать данные блок за блоком, передавая состояния агрегации в целевую таблицу без сохранения исходных строк.Для дополнительной безопасности рассмотрите возможность направить materialized view для дозагрузки во временную целевую таблицу (например,
otel_traces_1m_v2). После успешного завершения дозагрузки партиции можно переместить в основную целевую таблицу, например: ALTER TABLE otel_traces_1m_v2 MOVE PARTITION '2026-01-02' TO otel_traces_1m. Это позволит легко восстановиться, если дозагрузка будет прервана или завершится ошибкой из-за ограничений ресурсов.Рекомендации
Выбор и согласование гранулярности
- Временные диаграммы (линейные или столбчатые диаграммы со временем по оси x): Явно заданная гранулярность диаграммы должна быть кратна гранулярности materialized view. Например, диаграмма с 10-минутной гранулярностью может использовать materialized views с гранулярностью 10, 5, 2 или 1 минута, но не представления с гранулярностью 20 или 3 минуты.
-
Диаграммы без временной оси (числовые, табличные или сводные диаграммы):
Эффективная гранулярность вычисляется как
(time range / 80)с округлением вверх до ближайшей гранулярности, поддерживаемой HyperDX. Эта вычисленная гранулярность также должна быть кратна гранулярности materialized view.
- Не создавайте materialized views с 10-минутной гранулярностью. ClickStack поддерживает 15-минутную гранулярность для диаграмм и оповещений, но не 10-минутную. Поэтому materialized view с 10-минутной гранулярностью будет несовместимо с распространёнными 15-минутными визуализациями и оповещениями.
- Предпочтительнее гранулярность 1 минута или 1 час, так как она хорошо сочетается с большинством конфигураций диаграмм и оповещений.
Ограничивайте количество и объединяйте materialized view
- Не более 20 materialized views на источник.
- Около 10 materialized views обычно является оптимальным вариантом.
- Объединяйте несколько визуализаций в одно view, если у них общие измерения.
Тщательно выбирайте измерения
- Каждый дополнительный столбец группировки увеличивает размер представления.
- Балансируйте гибкость запросов и затраты на хранилище и вставку.
- Фильтры по столбцам, которых нет в представлении, приведут к тому, что ClickStack будет обращаться к исходной таблице.
СоветРаспространённый и почти всегда полезный базовый вариант — materialized view, сгруппированное по имени сервиса с метрикой count. Это позволяет быстро строить гистограммы и получать обзоры по сервисам в Search и на панелях мониторинга.
Соглашения об именовании столбцов агрегации
- Шаблон:
<aggFn>__<sourceColumn> - Примеры:
avg__Durationmax__Durationcount__для подсчёта строк
Квантили и выбор скетча
quantilesсоздает на диске более крупные скетчи, но их вычисление во время вставки обходится дешевле.quantileTDigestдороже в вычислении во время вставки, но создает меньшие скетчи, что часто ускоряет запросы к представлениям.
quantile(0.5) во время вставки. Получившийся скетч затем можно использовать в запросах и для других значений квантилей, например quantile(0.95). Рекомендуется поэкспериментировать, чтобы найти оптимальный баланс для вашей рабочей нагрузки.
Непрерывно проверяйте эффективность
- Проверяйте их использование по индикаторам ускорения в интерфейсе.
- Сравнивайте производительность запросов до и после включения представления.
- Отслеживайте потребление ресурсов и поведение при слиянии.
Расширенные конфигурации
- Недавние данные с высоким разрешением и укрупненные исторические представления
- Представления на уровне сервиса для общего обзора и представления на уровне конечных точек для углубленной диагностики
Ограничения
Распространённые причины несовместимости
- Временной диапазон запроса Начало временного диапазона запроса приходится на момент раньше минимальной временной метки materialized view. Поскольку materialized view не дозагружаются автоматически, они могут обслуживать только те запросы для временных диапазонов, которые покрывают полностью.
-
Несоответствие гранулярности
Эффективная гранулярность визуализации должна быть точным кратным гранулярности materialized view. В частности:
- Для временных диаграмм (линейных или столбчатых диаграмм со временем по оси x) выбранная гранулярность диаграммы должна быть кратна гранулярности представления. Например, диаграмма с шагом 10 минут может использовать materialized view с шагом 10, 5, 2 или 1 минута, но не с шагом 20 минут или 3 минуты.
- Для диаграмм без временной оси (числовых или табличных диаграмм) эффективная гранулярность вычисляется как
(time range / 80), округляется вверх до ближайшей гранулярности, поддерживаемой HyperDX, и также должна быть кратна гранулярности представления.
- Неподдерживаемые функции агрегации В запросе используется агрегация, которой нет в materialized view. Можно использовать только те агрегации, которые явно вычислены и сохранены в представлении.
-
Пользовательские выражения count
Запросы, использующие выражения вроде
count(if(...))или другие условные подсчёты, нельзя вывести из стандартных состояний агрегации, поэтому они не могут использовать materialized view.
Ограничения проектирования и эксплуатации
- Без автоматической дозагрузки Incremental materialized view содержат только данные, вставленные после их создания. Для ускорения запросов по историческим данным требуется явная дозагрузка, которая может оказаться дорогой или непрактичной для больших объёмов данных.
- компромиссы гранулярности Представления с очень высокой гранулярностью увеличивают объём хранилища и накладные расходы при вставке, тогда как более грубая гранулярность снижает гибкость. Гранулярность нужно тщательно подбирать в соответствии с ожидаемыми шаблонами запросов.
- взрывной рост размерностей Добавление большого числа размерностей группировки существенно увеличивает размер представления и может снизить его эффективность. В представления следует включать только часто используемые столбцы для группировки и фильтрации.
- ограниченная масштабируемость числа представлений Каждое materialized view добавляет накладные расходы при вставке и усиливает merge pressure. Создание слишком большого числа представлений может негативно повлиять на ингестию и фоновые слияния.
Устранение неполадок
Materialized view не используется
- Откройте модальное окно оптимизации и проверьте, отображается ли сообщение “Date range not supported.”
- Убедитесь, что диапазон дат в запросе начинается после минимальной даты materialized view.
- Удалите минимальную дату, если materialized view содержит все исторические данные.
- Убедитесь, что гранулярность графика кратна гранулярности MV.
- Попробуйте установить для графика значение “Auto” или вручную выбрать совместимую гранулярность.
- Проверьте, использует ли график агрегации, присутствующие в MV.
- Просмотрите раздел “Available aggregated columns” в модальном окне оптимизации.
- Убедитесь, что столбцы группировки входят в список столбцов измерений MV.
- Проверьте раздел “Available group/filter columns” в модальном окне оптимизации.
Медленные запросы к materialized view
- В MV слишком много строк из-за слишком мелкой гранулярности (например, 1 секунда).
- Решение: создайте MV с более грубой гранулярностью (например, 1 минута или 1 час).
- MV имеет высокую мощность из-за большого количества столбцов измерений.
- Решение: сократите число столбцов измерений до наиболее часто используемых.
- Система выполняет
EXPLAINдля каждого MV. - Решение: удалите MV, которые используются редко или постоянно пропускаются.
Ошибки конфигурации
- Добавьте в конфигурацию MV хотя бы один агрегированный столбец.
- Укажите, какой столбец нужно агрегировать (только для count столбец-источник можно не указывать).
- Используйте одно из предустановленных значений гранулярности в выпадающем списке.
- Формат должен быть корректным SQL-интервалом (например,
1 hour, а не1 h).