Перейти к основному содержанию
Это руководство входит в подборку выводов и рекомендаций, собранных на встречах сообщества. Больше практических решений и полезных наблюдений можно найти в подборке по конкретным проблемам. Возникли сложности с Materialized Views? Ознакомьтесь с руководством сообщества Materialized Views. Если у вас медленные запросы и вам нужно больше примеров, у нас также есть руководство Оптимизация запросов.

Упорядочивайте по мощности (от меньшей к большей)

Первичный индекс ClickHouse работает лучше всего, когда сначала идут столбцы с низкой мощностью: это позволяет эффективно пропускать большие фрагменты данных. Столбцы с высокой мощностью, расположенные дальше в ключе, обеспечивают более точную сортировку внутри этих фрагментов. Начинайте со столбцов с небольшим числом уникальных значений (например, status, category, country) и заканчивайте столбцами с большим числом уникальных значений (например, user_id, timestamp, session_id). Дополнительную информацию о мощности и первичных индексах см. в документации:

Важна гранулярность времени

При использовании временных меток в предложении ORDER BY учитывайте компромисс между мощностью и точностью. Временные метки с точностью до микросекунд создают очень высокую мощность (почти по одному уникальному значению на строку), что снижает эффективность разреженного первичного индекса ClickHouse. Округлённые временные метки создают меньшую мощность, благодаря чему индекс может эффективнее пропускать данные, но при этом вы теряете точность при выполнении запросов по времени.
runnable editable

Сосредоточьтесь на отдельных запросах, а не на средних значениях

При отладке производительности ClickHouse не полагайтесь на среднее время выполнения запросов или общие системные метрики. Вместо этого выясняйте, почему медленно выполняются конкретные запросы. Система может в среднем работать хорошо, даже если отдельные запросы упираются в нехватку памяти, неэффективную фильтрацию или операции над множествами высокой мощности. По словам Алексея, CTO ClickHouse: “Правильный подход — спросить себя, почему именно этот запрос выполнялся пять секунд… Мне не важно, что медиана и другие запросы выполняются быстро. Меня волнует только мой запрос” Когда запрос выполняется медленно, не ограничивайтесь средними значениями. Спросите: “Почему ЭТОТ конкретный запрос был медленным?” — и изучите фактическое потребление ресурсов.

Память и сканирование строк

Sentry — это платформа для отслеживания ошибок, ориентированная на разработчиков и ежедневно обрабатывающая миллиарды событий от более чем 4 миллионов разработчиков. Их ключевое наблюдение: “Именно мощность ключа группировки в этой конкретной ситуации будет определять потребление памяти” — агрегации с высокой мощностью ухудшают производительность из-за исчерпания памяти, а не из-за сканирования строк. Когда запросы завершаются с ошибкой, определите, связана ли проблема с памятью (слишком много групп) или со сканированием (слишком много строк). Запрос вида GROUP BY user_id, error_message, url_path создает отдельное состояние в памяти для каждой уникальной комбинации всех трех значений. При большом числе пользователей, типов ошибок и URL-путей можно легко получить миллионы состояний агрегации, которые должны одновременно храниться в памяти. В крайних случаях Sentry использует детерминированное сэмплирование. Выборка в 10% снижает использование памяти на 90%, сохраняя при этом примерно 5% точности для большинства агрегаций:
Это гарантирует, что в каждом запросе будут появляться одни и те же пользователи, обеспечивая согласованные результаты в разные периоды времени. Ключевая идея: cityHash64() выдает одинаковые хеш-значения для одного и того же входного значения, поэтому user_id = 12345 всегда будет хешироваться в одно и то же значение. Это гарантирует, что этот пользователь либо всегда попадает в вашу 10%-ную выборку, либо не попадает в нее никогда — без «мерцания» между запросами.

Оптимизация битовых масок в Sentry

При агрегации по столбцам с высокой мощностью (например, URL) каждое уникальное значение создаёт в памяти отдельное состояние агрегации, что может привести к её исчерпанию. Решение Sentry: вместо группировки по самим строкам URL использовать группировку по булевым выражениям, которые сворачиваются в битовые маски. Вот запрос, который можно попробовать на ваших таблицах, если у вас возникает такая ситуация:
Вместо того чтобы хранить в памяти каждую уникальную строку, вы сохраняете в виде целых чисел ответы на вопросы об этих строках. В результате состояние агрегации остаётся строго ограниченным и очень компактным независимо от разнообразия данных. Из инженерной команды Sentry: “Эти тяжёлые запросы выполняются более чем в 10 раз быстрее, а использование памяти у нас в 100 раз ниже (и, что ещё важнее, остаётся ограниченным). Наши крупнейшие клиенты больше не сталкиваются с ошибками при поиске replay, и теперь мы можем поддерживать клиентов любого масштаба, не упираясь в ограничения памяти.”

Источники видео

Читайте далее:
Последнее изменение 3 июля 2026 г.