Как оптимизировать многопоточную обработку в ClickHouse и эффективно распределить ресурсы ЦП между разными пользователями и запросами, спланировав рабочую нагрузку.
Настройка многопоточной обработки в Clickhouse
Чтобы эффективно утилизировать ресурсы для аналитической обработки огромных объемов данных, в ClickHouse можно спланировать рабочую нагрузку, определив приоритеты использования памяти, диска и ЦП для разных видов запросов. Поскольку ClickHouse изначально спроектирован для многопоточной обработки на всех ядрах ЦП, в СУБД есть возможности настроить параметры потоков.
Каждый SQL-запрос делится на несколько этапов, таких как парсинг, оптимизация, выполнение и передача результатов. Это разделение выполняет главный поток, распределяя работу по выполнению этапов между рабочими потоками. Этапы выполнения запроса обрабатываются рабочими потоками параллельно. Для обработки запросов и выполнения фоновых операций слияния и мутации ClickHouse использует потоки из глобального пула потоков Global Thread. Максимальный размер глобального пула потоков определяется настройкой max_thread_pool_size, которая по умолчанию равна 10 000. Можно изменить это значение в конфигурационном XML-файле, задав нужное число в тегах <max_thread_pool_size>. При этом рекомендуется аналогичным образом поменять и параметр thread_pool_queue_size – максимальное количество заданий, которые могут быть запланированы в глобальном пуле потоков. Для управления количеством потоков фоновых задач настраивается background_pool_size. Большие размеры пула могут улучшить пропускную способность фоновых задач, но могут конкурировать с обработкой запросов за ресурсы ЦП.
Если нет свободного потока для обработки запроса, то в пуле создается новый поток. Можно также освободить ресурсы, если на сервере много бездействующих потоков, определив значение настройки max_thread_pool_free_size в конфигурационном XML-файле сервера ClickHouse. По умолчанию максимально допустимое количество бездействующих потоков равно 1000.
Отслеживать производительность, чтобы понять, сколько заданий обрабатывается пулом потоков, сколько времени тратится на блокировки и является ли создание потоков узким местом, поможет мониторинг следующих метрик:
- GlobalThreadPoolThreadCreationMicroseconds – время, необходимое для создания новых потоков. Позволяет определить, когда создание потоков становится потенциальным узким местом.
- GlobalThreadPoolExpansions и GlobalThreadPoolShrinks – показатели частоты расширения и сокращения глобального пула потоков. Они дают представление о том, насколько хорошо ClickHouse адаптируется к текущей рабочей нагрузке.
- GlobalThreadPoolJobs и LocalThreadPoolJobs – количество заданий, обработанных глобальными и локальными пулами потоков. Это тоже дает информацию о распределении рабочей нагрузки.
- GlobalThreadPoolJobWaitTimeMicroseconds и LocalThreadPoolJobWaitTimeMicroseconds – эти показатели отслеживают, как долго задания находятся в очереди глобального и локального пула потоков перед выполнением, выявляя любые задержки в планировании задач.
- GlobalThreadPoolLockWaitMicroseconds и LocalThreadPoolLockWaitMicroseconds – метрики измерения времени, которое потоки тратят на ожидание блокировок. Они помогают определить, где конфликты блокировок могут вызывать задержки.
Максимально возможное количество потоков для обработки одного запроса определяется значением параметра max_threads. Рекомендуется задавать его равным количеству физических ядер ЦП. В средах с высоким параллелизмом рекомендуется снизить это значение, чтобы распределить ресурсы ЦП между параллельными запросами. При этом важно помнить, что слишком большое количество потоков приводит к увеличению времени из-за переключения контекста и накладным расходам.
Если ЦП имеет многопроцессорную архитектуру NUMA (Non-Uniform Memory Access) с неравномерным доступом к памяти, где каждый процессор имеет быстрый доступ к локальной памяти через свой контроллер, а также более медленный канал до памяти, подключённой к контроллерам (слотам) других процессоров, реализуемый через шину обмена данными, можно повлиять на производительность потоков, используя утилиту numactl. Она позволяет управлять политиками распределения памяти и привязкой процессоров.
Для управления потоками слияния, которые тоже влияют на загрузку ЦП, настраиваются следующие параметры:
- merge_tree_max_rows_to_use_cache – использование кэша для операций слияния;
- max_bytes_to_merge_at_min_space_in_pool – размер слияний;
- max_insert_threads – количество потоков для операций вставки в таблицах с движком MergeTree. Этот параметр позволяет распараллеливать операции вставки. И обычно устанавливается на основе количества ядер ЦП и ожидаемых рабочих нагрузок вставки.
- max_distributed_connections – количество подключений к удаленным серверам, что влияет влияя на потоки, связанные с сетью. Можно увеличить этот параметр, если распределенные запросы ограничены вводом-выводом и ресурсов ЦП достаточно.
Чтобы сбалансировать обслуживания нескольких одновременных запросов с преимуществами параллельного выполнения отдельных запросов, следует настроить планирование рабочей нагрузки ЦП, что мы и рассмотрим далее.
Планирование нагрузки ЦП
Настроить планирование нагрузки ЦП в ClickHouse можно следующими способами:
- глобальные настройки в конфигурационных XML-файлах;
- настройки на уровне пользовательских профилей в XML-файлах;
- SQL-команды.
В ClickHouse 25.4, вышедшем в апреле 2025 года, добавлено планирование слотов ЦП для рабочих нагрузок, что позволяет ограничивать количество одновременных потоков для определенной рабочей нагрузки. Эта функция позволяет совместно использовать кластеры ClickHouse между различными рабочими нагрузками и обеспечивать взвешенное справедливое распределение и распределение на основе приоритетов для ресурсов ЦП. Благодаря этому можно выполнять тяжеловесные специальные запросы, не влияя на высокоприоритетные отчеты в реальном времени.
Для планирования нагрузки ЦП сперва нужно определить этот ресурс, например, с помощью SQL:
CREATE RESOURCE cpu (MASTER THREAD, WORKER THREAD);
После этого можно настроить максимальное количество одновременно выполняемых запросов, задав значение max_concurrent_threads для управления распределением потоков ЦП. Без объявления ресурса ЦП ClickHouse будет использовать настройки управления параллелизмом на уровне сервера concurrent_threads_soft_limit_num и связанные настройки.
Чтобы добиться лучшей отзывчивости, можно использовать отдельные ресурсы для главного потока и рабочих потоков:
CREATE RESOURCE master_cpu (MASTER THREAD); CREATE RESOURCE worker_cpu (WORKER THREAD);
Определив ресурсы, можно создавать рабочие нагрузки, использующие их. Например, аналитические запросы требуют больше потоков на запрос при меньшем количество конкурентных запросов. А операции ввода-вывода – наоборот, меньше потоков на запрос, но больше конкурентных запросов. Для фоновых операций слияния и мутаций можно выделить отдельный пул с контролируемой конкуренцией.
-- Создание рабочей нагрузки для аналитических запросов с использованием worker_cpu CREATE WORKLOAD analytics ( RESOURCE worker_cpu MAX 70 PERCENT, -- Использовать максимум 70% ресурса worker_cpu USER REQUESTS PER SECOND MAX 10, -- Ограничение по количеству запросов в секунду QUERY DURATION MAX 60 SECOND -- Максимальная продолжительность запроса ); -- Создание рабочей нагрузки для операций ввода данных с использованием master_cpu CREATE WORKLOAD ingestion ( RESOURCE master_cpu MAX 40 PERCENT, -- Максимум 40% ресурса master_cpu MEMORY MAX 20 GB, -- Максимальное использование памяти QUERY MEMORY MAX 5 GB -- Максимальная память на запрос ); -- Создание рабочей нагрузки для отчетов с использованием обоих ресурсов CREATE WORKLOAD reporting ( RESOURCE worker_cpu MAX 50 PERCENT, -- Максимум 50% worker_cpu RESOURCE master_cpu MAX 20 PERCENT, -- Максимум 20% master_cpu QUERY REQUESTS PER SECOND MAX 5, -- Максимум 5 запросов в секунду PRIORITY LOW -- Низкий приоритет выполнения );
После создания рабочих нагрузок, можно привязать их к конкретным пользователям, ролям или запросам:
-- Привязка рабочей нагрузки к пользователю ALTER USER analyst SET WORKLOAD analytics; -- Привязка рабочей нагрузки к роли ALTER ROLE data_engineer SET WORKLOAD ingestion; -- Использование рабочей нагрузки для конкретного запроса SELECT * FROM large_table WHERE condition SETTINGS workload='reporting'; Можно также динамически изменять параметры рабочих нагрузок: -- Изменение рабочей нагрузки ALTER WORKLOAD analytics MODIFY RESOURCE worker_cpu MAX 80 PERCENT, -- Увеличение лимита CPU MODIFY QUERY DURATION MAX 120 SECOND; -- Увеличение максимального времени запроса -- Включение и отключение рабочих нагрузок ALTER WORKLOAD ingestion ENABLE; ALTER WORKLOAD reporting DISABLE;
Таким образом, ClickHouse позволяет эффективно распределять ресурсы между различными типами задач, обеспечивая баланс между отзывчивостью системы и эффективностью выполнения запросов. Такое управление ресурсами особенно полезно в многопользовательских средах, где разные группы пользователей выполняют разные типы задач с различными требованиями к ресурсам и необходимостью обеспечить оптимальную производительность системы в целом.
Узнайте больше про администрирование и эксплуатацию ClickHouse на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
Источники
- https://altinity.com/blog/unraveling-the-mystery-of-idle-threads-in-clickhouse
- https://chistadata.com/mastering-clickhouse-thread-tuning/
- https://chistadata.com/optimizing-thread-scheduling-in-clickhouse/
- https://clickhouse.com/docs/knowledgebase/how-to-increase-thread-pool-size
- https://clickhouse.com/docs/operations/workload-scheduling
- https://clickhouse.com/blog/clickhouse-release-25-04