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

ClickHouse 25.5 и параллельный merge: тестируем на телеметрии IoT-датчиков

ClickHouse 25.5 получил параллельный merge партов и новые функции для временных рядов. Проверяем на реальной IoT-телеметрии: насколько легче ночные ETL-окна.

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

ClickHouse 25.5 с улучшенным параллельным слиянием партов и новыми функциями работы с временными рядами

ClickHouse 25.5 вышел в начале мая. Два изменения зацепили сразу: переработанный параллельный merge партов в MergeTree и набор новых функций для работы с временными рядами. У нас как раз есть стенд, где эти вещи можно проверить в условиях, близких к продуктиву, - IoT-телеметрия с нескольких сотен датчиков на производственном объекте клиента. Обновились и посмотрели.

Контекст: почему merge - это боль

Тем, кто не работал вплотную с MergeTree, поясним. ClickHouse при вставке данных не пишет их в одно место - он создаёт отдельные парты (data parts), которые потом фоново сливает (мёрджит) в более крупные. Это и есть основа высокой скорости вставки, но обратная сторона - фоновый процесс слияния постоянно жрёт ресурсы: CPU, I/O, память.

На IoT-стенде это особенно заметно. Датчики пишут данные равномерно весь день, но ночью клиент гоняет ETL-пайплайны: пересчёт агрегатов, заливка исторических поправок, пересборка материализованных представлений. В итоге ночное окно - это одновременно пик записи от ETL и пик фонового merge. Сервер в такие моменты вёл себя нервно: latency запросов росла, иногда срабатывал too many parts и вставки начинали тормозить.

Что изменилось в 25.5

До 25.5 merge в MergeTree был преимущественно однопоточным на уровне одного слияния. Параллелизм достигался запуском нескольких независимых merge-задач, но каждая из них внутри шла последовательно. В 25.5 движок научился распараллеливать чтение партов внутри одной задачи слияния - грубо говоря, читает несколько партов одновременно, а не поочерёдно.

Для машин с быстрыми NVMe и достаточным числом ядер это должно снизить время одного слияния и сократить накопление партов в очереди. На бумаге звучит хорошо. Проверяем на практике.

Стенд и методология

IoT-стенд: несколько сотен датчиков, данные пишутся каждые несколько секунд, общий объём таблицы телеметрии - несколько сотен миллионов строк, прирост около 50-80 млн строк в сутки в активный период. Сервер - 32-ядерная машина с NVMe-накопителями, RAM 128 ГБ. Версию подняли с 25.3 до 25.5 в тестовой среде с реальными данными.

Смотрели на три вещи:

  • Количество партов в таблице в динамике за ночное окно - сколько успевает накопиться и как быстро схлопывается.
  • Время выполнения ETL-задач - насколько быстрее или медленнее они проходят при параллельном merge.
  • Latency SELECT-запросов во время активного merge - это то, что клиент ощущает напрямую.

Что наблюдали

Количество партов. На 25.3 в пик ночного ETL очередь партов разрасталась до нескольких сотен, и merge не успевал за вставками - типичная картина, когда прилетает много мелких батчей. На 25.5 та же нагрузка даёт заметно меньше накопившихся партов в пике: параллельное чтение внутри merge-задачи ускоряет схлопывание, и очередь не разрастается так сильно. До too many parts не дошли ни разу за несколько ночных прогонов.

ETL-задачи. Здесь сюрприз: задачи, которые делают много мелких вставок (заливка исторических поправок партиями по несколько тысяч строк), прошли немного быстрее. Задачи, которые пересчитывают агрегаты через INSERT INTO ... SELECT, особой разницы не показали - там узкое место не merge, а сам SELECT.

Latency SELECT. Заметное улучшение именно в моменты активного merge. Раньше в такие окна аналитические запросы по телеметрии иногда уходили за несколько секунд вместо привычных сотен миллисекунд. На 25.5 провалов стало меньше - merge не так агрессивно конкурирует за I/O с читающими запросами.

Новые функции для временных рядов

Параллельно с merge в 25.5 добавили несколько функций, специфичных для time series: seriesDecomposeSTL и seriesOutliersDetectTukey - разложение временного ряда на тренд/сезонность/остаток и детектор выбросов по методу Тьюки прямо в SQL.

Для IoT-телеметрии это интересно. Раньше для похожих задач мы тащили данные в Python, делали декомпозицию там, писали результат обратно. Теперь можно попробовать сделать это запросом. Успели только быстро пощупать: seriesOutliersDetectTukey на наших рядах работает предсказуемо, возвращает массив флагов выбросов. seriesDecomposeSTL - чуть медленнее, чем хотелось бы на длинных рядах, но для разовой аналитики вполне годится. Для потокового использования в дашборде смотреть надо отдельно.

Что пока не тестировали

Параллельный merge зависит от настроек - в частности, от max_threads и новых параметров, которые появились в 25.5. Мы пока гоняли на дефолтах, чтобы понять базовое поведение. Тюнинг под конкретные характеристики железа - следующий шаг.

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

Итог

Обновление на 25.5 в тестовой среде показало реальное улучшение именно в той точке, которая нас беспокоила - накопление партов и latency во время ночных ETL-окон. Параллельный merge работает, и на NVMe-железе с нормальным числом ядер разница ощутима.

На продуктив клиента переходить пока рано - хотим ещё прогнать с настройками, проверить на реплицируемом кластере. Но направление правильное. Для аналитики на ClickHouse с высокой частотой записи это одно из более полезных улучшений за последние несколько релизов.

Контакт

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

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