ADG Оставить заявку
Блог Данные и аналитика 4 мин чтения

ClickHouse 22.12: тестируем parallel replicas на аналитическом кластере

ClickHouse 22.12 добавил экспериментальную функцию parallel replicas. Тестируем на реальном кластере: где прирост существенный, а где лучше не включать.

Контекст момента

ClickHouse 22.12 - экспериментальная функция parallel replicas для ускорения запросов на кластере

ClickHouse 22.12 вышел в этот вторник. В списке изменений много всего, но нас сейчас интересует одна вещь: экспериментальная функция parallel_replicas_for_non_replicated_merge_tree. Идея - использовать реплики не как резерв на случай падения, а как дополнительные вычислительные ресурсы для обработки одного запроса. Функция помечена как экспериментальная, но задокументирована достаточно, чтобы её попробовать осознанно.

У одного из клиентов сейчас работает аналитический кластер - трёхнодовый ReplicatedMergeTree, несколько сотен гигабайт горячих данных на узлах. Исторически реплики использовались для отказоустойчивости и балансировки нагрузки между пользователями. Мы решили потестировать, что даёт parallel replicas для тяжёлых аналитических запросов.

Как это работает

В обычной схеме запрос к реплицированной таблице обрабатывает один узел - тот, к которому пришёл запрос. Остальные реплики простаивают. С parallel_replicas координатор делит гранулы (блоки данных) между всеми доступными репликами и собирает результаты. Получается что-то похожее на то, как ClickHouse распараллеливает запросы внутри одного узла по ядрам CPU, только теперь ещё и между узлами.

Включается на уровне сессии или запроса:

SET allow_experimental_parallel_reading_from_replicas = 1;
SET max_parallel_replicas = 3;
SET prefer_localhost_replica = 0;

prefer_localhost_replica = 0 - важный флаг. Без него координатор склонен обрабатывать данные локально, что убивает весь смысл.

Где прирост есть

Полные сканирования больших таблиц. Запросы типа агрегатов по всей истории - суммы, подсчёты уникальных значений, перцентили - ускорились в два-три раза. Это максимально близко к теоретическому пределу при трёх репликах: каждая обрабатывает треть гранул, результаты сливаются. Реальный прирост чуть ниже теоретического из-за накладных расходов на координацию и финальное слияние на координаторе.

Запросы с тяжёлой фильтрацией по некластеризованным колонкам. Когда ClickHouse не может срезать много данных через первичный ключ и вынужден читать большой объём - parallel replicas помогают. Нагрузку на I/O делим между репликами, каждая читает своё.

COUNT DISTINCT с высокой кардинальностью. Заметное ускорение - координация HyperLogLog между узлами работает хорошо.

Где лучше не включать

Запросы с точечным поиском по первичному ключу. Если запрос обращается к нескольким гранулам по конкретному диапазону дат или ID - накладные расходы на координацию съедают выигрыш. Запрос, который и так выполняется за 50-100 мс, с parallel replicas может выполняться за 150 мс: три узла нужно опросить, синхронизировать, собрать результат.

Небольшие таблицы и LIMIT-запросы. Если данных мало - нет смысла делить их между репликами. ClickHouse умеет останавливать чтение при достижении LIMIT, но с parallel replicas это работает менее эффективно: координатор должен договориться с репликами о завершении, это лишние round-trip-ы.

Запросы на кластере под высокой нагрузкой. Один тяжёлый запрос с parallel replicas теперь занимает ресурсы всех трёх узлов одновременно. Если в это же время другие аналитики запускают свои запросы - они тоже получают все три узла в более нагруженном состоянии. На нашем тестовом окружении при одновременных запросах нескольких пользователей суммарная пропускная способность кластера не выросла, зато задержки у всех стали чуть хуже.

Что нужно проверить до включения

Функция экспериментальная - это не просто предупреждение. Мы столкнулись с тем, что при определённых запросах с GROUP BY на больших объёмах координатор потреблял заметно больше памяти, чем ожидалось. Ничего не упало, но за этим нужно следить. В system.query_log смотрим на memory_usage и ProfileEvents.ReadBufferFromFileDescriptorReadBytes - они дают понять, какой узел реально тянет основной объём.

Также стоит убедиться, что у всех реплик примерно одинаковая нагрузка и состояние. Если одна реплика отстаёт в репликации - она будет тормозить весь параллельный запрос, координатор ждёт самого медленного участника.

Итог на сейчас

Для тяжёлых аналитических запросов на больших таблицах - попробовать стоит. На кластере клиента включили parallel replicas на уровне конкретного пользователя BI-системы, который строит тяжёлые агрегаты. Интерактивные дашборды с быстрыми точечными запросами оставили без изменений.

Идея включить это для всех подряд - плохая. Нужен профиль нагрузки: какие запросы тяжёлые и редкие, какие лёгкие и частые. Первым - parallel replicas, вторым - нет.

Функция в 22.12 сырая, но направление интересное. Если раньше горизонтальное масштабирование ClickHouse означало либо шардирование, либо просто резервирование - теперь есть третий вариант: реплики как дополнительные вычислительные ресурсы для одного запроса. Это меняет расчёт при проектировании кластера для аналитической инфраструктуры.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.