Оптимизация производительности: проверенные стратегии сообщества
Этот гид является частью набора выводов, полученных на встречах сообщества. Для получения дополнительных решений и идей вы можете просмотреть по конкретной проблеме. Проблемы с материализованными представлениями? Ознакомьтесь с гидом по Материализованным представлениям от сообщества. Если у вас медленные запросы и вам нужно больше примеров, у нас также есть гид по Оптимизации запросов.
Порядок по кардинальности (от низкой к высокой)
Первичный индекс ClickHouse работает лучше всего, когда колонки с низкой кардинальностью идут первыми, что позволяет эффективно пропускать большие объемы данных. Колонки с высокой кардинальностью, расположенные позже в ключе, обеспечивают детальную сортировку внутри этих объемов. Начинайте с колонок, имеющих несколько уникальных значений (например, статус, категория, страна), и заканчивайте колонками с множеством уникальных значений (например, user_id, timestamp, session_id).
Изучите дополнительные материалы о кардинальности и первичных индексах:
Важность временной гранулярности
При использовании временных меток в вашем операторе ORDER BY учитывайте компромисс между кардинальностью и точностью. Микросекундные метки создают очень высокую кардинальность (почти одно уникальное значение на строку), что снижает эффективность разреженного первичного индекса ClickHouse. Округленные временные метки создают более низкую кардинальность, что позволяет лучше пропускать индексы, но при этом вы теряете точность для временных запросов.
Сосредоточьтесь на отдельных запросах, а не на средних значениях
При отладке производительности ClickHouse не полагайтесь на среднее время запросов или общие системные метрики. Вместо этого определите, почему конкретные запросы работают медленно. Система может демонстрировать хорошую среднюю производительность, в то время как отдельные запросы страдают от исчерпания памяти, плохой фильтрации или операций с высокой кардинальностью.
По словам Алексея, CTO ClickHouse: "Правильный подход - задать себе вопрос, почему этот конкретный запрос был обработан за пять секунд... Неважно, если медианные и другие запросы обрабатываются быстро. Мне важно только моё выполнение запроса."
Когда запрос работает медленно, не ограничивайтесь средними значениями. Спросите: "Почему THIS конкретный запрос был медленным?" и изучите фактические паттерны использования ресурсов.
Память и сканирование строк
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 раз ниже (и, что более важно, ограничено). Наши крупнейшие клиенты больше не видят ошибок при поиске реплеев, и теперь мы можем поддерживать клиентов произвольного размера без исчерпания памяти."
Видеоресурсы
- Потерянные в стоге сена - Оптимизация агрегаций с высокой кардинальностью - Уроки Sentry по оптимизации памяти
- Анализ производительности ClickHouse - Алексей Миловидов о методологии отладки
- Встреча ClickHouse: Техники оптимизации запросов - Стратегии оптимизации сообщества
Читайте далее: