ClickHouse в продакшене: шардирование, MergeTree и оптимизация запросов
ClickHouse легко влюбляет в себя на старте. Первые запросы выполняются за миллисекунды, данные заливаются миллионами строк, и создаётся ощущение, что дальше всё будет так же просто. Проблемы начинаются позже, когда объёмы растут, запросы усложняются, а система внезапно перестаёт быть «просто быстрой».
В продакшене ClickHouse требует осознанных решений. Причём не столько на уровне оптимизации запросов, сколько на уровне архитектуры таблиц и распределения данных.
MergeTree: где всё начинается
Практически любая продакшен-таблица в ClickHouse — это MergeTree или его вариации. И именно здесь чаще всего закладываются будущие проблемы.
На первый взгляд определение таблицы выглядит довольно стандартно:
Но на самом деле ORDER BY — это не логический порядок, а физическая сортировка данных на диске. От него напрямую зависит, сколько данных ClickHouse будет читать при каждом запросе. Если большинство запросов фильтруются по дате, такой порядок работает отлично. Если же фильтры идут по другим полям, движок вынужден читать значительно больше данных, чем кажется по условиям WHERE.
На практике хорошее ORDER BY почти всегда:
• Совпадает с самыми частыми фильтрами, • Начинается с поля с относительно низкой кардинальностью, • Отражает реальные сценарии запросов, а не абстрактную модель данных.
PRIMARY KEY в ClickHouse — это не OLTP
Часто в схемах можно увидеть что-то вроде:
В ClickHouse это почти бесполезно. Здесь PRIMARY KEY не обеспечивает уникальность и не работает как индекс в классических БД. По сути, это механизм data skipping, который помогает быстрее пропускать ненужные части данных.
Если по полю почти никогда не фильтруются, оно не должно быть в PRIMARY KEY, даже если логически выглядит «главным».
Партиционирование без фанатизма
Партиции — ещё одно место, где легко переборщить. Делить таблицу по дням выглядит логично, но в продакшене это часто приводит к слишком большому количеству частей и дорогим merge-операциям.
Чаще всего разумный баланс выглядит так:
Это позволяет:
• Удобно управлять жизненным циклом данных, • Не создавать тысячи мелких партиций, • Сохранять стабильную работу merge-процессов.
Шардирование: решение, которое сложно отменить
Шардирование в ClickHouse — это не просто масштабирование, а стратегический выбор. Неправильно выбранный шард-ключ может сделать каждый запрос распределённым и непредсказуемым по времени выполнения.
Пример типичного шардирования:
Такой подход хорошо работает, если:
• Большинство запросов фильтруется по account_id, • Данные распределяются относительно равномерно, • Агрегации можно выполнять локально на шарде.
А вот шардирование по случайным значениям или UUID часто приводит к ситуации, когда каждый запрос ходит во все шарды, независимо от условий.
Distributed-таблицы: скрытая цена
Distributed выглядит как удобная абстракция:
Но за этим простым запросом может скрываться обращение ко всему кластеру. Особенно если фильтр не затрагивает шард-ключ.
В продакшене это означает:
• Сетевые накладные расходы, • Агрегацию результатов на координаторе, • Рост времени ответа при увеличении числа шардов.
Поэтому запросы к Distributed-таблицам почти всегда стоит рассматривать отдельно и осознанно.
Оптимизация запросов: простые вещи решают больше всего
Чаще всего проблемы начинаются не с экзотических кейсов, а с базовых ошибок.
Например, SELECT *:
Даже если используется фильтр по дате, ClickHouse всё равно читает все колонки, включая тяжёлые JSON-поля или строки. Явное указание нужных колонок почти всегда даёт заметный прирост.
Фильтры, совпадающие с ORDER BY, позволяют ClickHouse читать меньше данных. А вынесение простых условий в PREWHERE помогает отсеять строки до чтения всех колонок:
Агрегации и память
Некоторые функции выглядят безобидно, но в продакшене быстро становятся проблемой:
• countDistinct • uniqExact • groupArray
На больших объёмах они могут потреблять гигабайты памяти. Часто вместо них разумнее использовать приближённые варианты или предварительные агрегации.
Материализованные представления как часть дизайна
В продакшене рано или поздно приходит понимание: не все данные нужно агрегировать в момент запроса.
Материализованные представления позволяют считать агрегаты при записи:
ClickHouse в продакшене — это не история про «быструю базу», а про осознанную работу с данными. Хорошо выбранный ORDER BY, адекватное партиционирование, аккуратное шардирование и понятные запросы дают стабильную производительность без постоянного тюнинга. Именно этот баланс между архитектурой и запросами и отличает рабочий продакшен от красивого демо.
Хотите узнать больше? Изучите другие статьи из раздела: