Выберите продукт

ClickHouse on VDS 2026: MergeTree parts, merges и память без сюрпризов

Разбираем, почему ClickHouse на VDS внезапно «роняет» SELECT: рост MergeTree parts, фоновые merges, влияние INSERT и конкуренция за диск. Даю чеклист диагностики и практику по max_memory_usage, overcommit и настройке mark/uncompressed cache.
ClickHouse on VDS 2026: MergeTree parts, merges и память без сюрпризов

ClickHouse в 2026 году по‑прежнему отлично подходит для быстрых агрегатов по большим объёмам данных. Но в production почти всегда упираются в два ресурса: дисковую подсистему и оперативную память. И чаще всего это проявляется не как «медленный диск», а как внезапные провалы по SELECT, рост задержек на INSERT и ошибки вроде too many parts.

Ниже — практическая эксплуатация на VDS: как MergeTree работает на уровне parts, что делают background merges, почему «много мелких кусков» ломает и чтение, и вставки, как читать системные таблицы, и как не загнать сервер в OOM из‑за лимитов max_memory_usage, overcommit и кэшей (mark/uncompressed cache).

Ментальная модель: что делает SELECT в MergeTree

Чтобы тюнить SELECT, важно понимать простую вещь: MergeTree читает не «таблицу», а набор parts (частей). Каждый part — самостоятельный кусок данных со своими файлами столбцов, индексом (primary key), метками (marks) и статистикой.

В типовом запросе ClickHouse делает следующее:

  • выбирает, какие parts нужно затронуть (партиции + индекс);
  • для каждого part определяет диапазоны marks, которые надо читать;
  • читает нужные столбцы, разжимает, применяет фильтры, агрегации/JOIN/сортировки;
  • упирается в I/O (много мелких чтений по marks) и в память (хэши агрегаций, JOIN, сортировки).

Вывод для эксплуатации: даже идеально написанный запрос начнёт деградировать, если parts стало слишком много или merges не успевают «склеивать» их в более крупные части.

Почему too many parts — это не только про вставки

Симптом too many parts часто воспринимают как «проблема вставок»: частые маленькие INSERT создают множество частей, и система начинает тратить ресурсы на их обслуживание. Но это напрямую бьёт и по чтению.

  • Планирование запроса: больше parts — больше работы на этапе подготовки, больше накладных расходов на диспетчеризацию.
  • Чтение по marks: множество маленьких частей превращают чтение в большое число маленьких I/O (особенно на сетевых/загруженных дисках).
  • Эффективность кэшей: рабочий набор размазывается по множеству файлов — hit-rate mark/uncompressed cache падает.

Если parts растут быстрее, чем merges их схлопывают, вы почти всегда увидите цепочку: сначала падает скорость вставок, затем «вдруг» начинают плавать задержки SELECT даже на старых запросах.

Схема: рост частей MergeTree и очередь background merges

Если вы упёрлись в диск или память и merges стабильно «не успевают», чаще всего проще и дешевле решить проблему ресурсами: добавить CPU/RAM и перейти на более быстрые диски на уровне тарифа VDS.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Background merges: что делают и почему могут «не успевать»

Background merges — это фоновое слияние частей (parts) в более крупные. В норме merges уменьшают количество частей, улучшают локальность данных, снижают накладные расходы на индексы и делают чтение более предсказуемым.

Почему merges не успевают (частые причины на VDS):

  • Слишком много мелких INSERT (например, каждые 1–2 секунды небольшая порция) без буферизации на стороне приложения/шины.
  • Диск не тянет: merge — это чтение + запись, иногда с высокой конкуренцией за IOPS и пропускную способность.
  • Конкуренция с SELECT: чтение и merges дерутся за I/O, latency начинает «пилить».
  • Неудачная партиционизация: слишком мелкие партиции увеличивают число активных частей и уменьшают шанс на «крупные» merges.
  • ORDER BY не соответствует фильтрам: merges не спасают, если запросы всё равно читают значительную долю данных.

Как быстро проверить состояние parts и merges

Начинайте с системных таблиц: они показывают реальную динамику и «узкое место», а не ощущения.

clickhouse-client -q "SELECT database, table, count() AS parts, sum(rows) AS rows, formatReadableSize(sum(bytes_on_disk)) AS size FROM system.parts WHERE active GROUP BY database, table ORDER BY parts DESC LIMIT 20"
clickhouse-client -q "SELECT database, table, elapsed, progress, num_parts, total_size_bytes_compressed FROM system.merges ORDER BY elapsed DESC LIMIT 20"
clickhouse-client -q "SELECT event_time, event_type, formatReadableSize(size) AS size, duration_ms, database, table, part_name FROM system.part_log WHERE event_type IN ('NewPart','MergeParts','MutatePart') ORDER BY event_time DESC LIMIT 50"

На что смотреть в первую очередь:

  • Лидеры по parts в system.parts: таблицы‑кандидаты на «генератор мелких частей».
  • Хвост merges в system.merges: какие таблицы и какие объёмы сливаются долго и постоянно.
  • Баланс NewPart vs MergeParts в system.part_log: если NewPart стабильно обгоняет MergeParts, деградация будет накапливаться.

INSERT performance: как не плодить мелкие parts

ClickHouse любит батчи. Если вставлять в production мелкими порциями, вы почти гарантированно придёте к тысячам/десяткам тысяч частей и деградации: merges станут постоянным фоном, а чтение начнёт «шуметь» задержками.

Практика, которая обычно даёт быстрый эффект:

  • Укрупняйте батчи: группируйте вставки по размеру или по времени (в разумных пределах).
  • Стабилизируйте частоту: ровная нагрузка почти всегда легче для merges, чем пики.
  • Избегайте сверхмелких партиций: партиция «по часу» может быть нормальной, но при большом потоке превращается в генератор parts.
  • Не размножайте INSERT по десяткам таблиц без нужды: parts и merges множатся линейно, а диск один.

Простейшая диагностика «вставки слишком мелкие»: в system.part_log много событий NewPart с маленьким размером, а merges не закрывают этот поток.

Память в SELECT: max_memory_usage, overcommit и «неочевидные» потребители

В ClickHouse «убийца» запросов чаще память, а не CPU. Риски по RAM повышают: агрегации с высокой кардинальностью, большие JOIN, сортировки, window‑функции, DISTINCT, чтение большого числа столбцов с распаковкой.

Удобно держать в голове три слоя потребления:

  • Память запроса — то, что ограничивается max_memory_usage и связанными лимитами.
  • Кэши — mark cache и uncompressed cache: ускоряют чтение, но «конкурируют» за RAM с запросами.
  • Фон — merges, мутации, служебные структуры сервера и память ОС.

max_memory_usage: почему «поставили побольше» иногда хуже

max_memory_usage ограничивает RAM на один запрос. Ошибка эксплуатации — выкрутить лимит «чтобы не падало». Тогда один тяжёлый отчёт может съесть почти всю память, вытеснить кэши, создать давление на память и спровоцировать лавинообразную деградацию для всех остальных запросов.

Рабочая схема в production:

  • задайте реалистичный лимит на запрос для приложения/обычных пользователей;
  • для админских сессий/ночных задач используйте отдельный профиль с повышенными лимитами;
  • учитывайте конкуренцию: два параллельных запроса по 50–60% RAM хуже, чем один на 80%.

Overcommit: как ClickHouse выбирает, кого «урезать»

Overcommit (в терминах настроек ClickHouse) нужен, чтобы при общем дефиците памяти сервер мог отменить один или несколько запросов и не довести систему до неконтролируемого OOM на уровне ОС.

Для production лучше контролируемо отменить один тяжёлый запрос, чем потерять весь инстанс и получить длинное восстановление.

Симптомы, которые часто указывают именно на память:

  • скачки latency на SELECT при росте параллелизма;
  • ошибки превышения памяти на части запросов;
  • заметное падение hit-rate кэшей после «тяжёлых отчётов»;
  • появление активного swap (для ClickHouse это почти всегда сигнал «пересмотреть лимиты/запросы»).

Mark cache и uncompressed cache: когда ускоряют SELECT, а когда мешают

Два кэша, с которыми чаще всего «перебарщивают» на небольших серверах:

  • mark cache — кэш меток (позиций) для чтения по первичному ключу и пропуска ненужных гранул. Обычно даёт пользу почти всегда, но размер должен быть разумным.
  • uncompressed cache — кэш разжатых блоков. Может резко ускорять повторяющиеся запросы, но потребляет заметно больше памяти.

На VDS типичная ошибка — увеличить кэши «как в рекомендациях из интернета», не учитывая профиль запросов. Если RAM мало, кэши начинают конкурировать с рабочей памятью запросов и merges, что даёт нестабильность: кэш то вытесняется, то снова заполняется.

Быстрая проверка текущего потребления кэшей:

clickhouse-client -q "SELECT metric, value FROM system.metrics WHERE metric IN ('MarkCacheBytes','UncompressedCacheBytes')"
clickhouse-client -q "SELECT metric, value FROM system.asynchronous_metrics WHERE metric IN ('MarkCacheSize','UncompressedCacheSize')"

Если кэши постоянно упираются в лимит, а запросы преимущественно «холодные» (редкие отчёты за большие диапазоны), часто выгоднее отдать память под запросы и merges, а кэш держать умеренным.

Графики мониторинга: память, кэши ClickHouse и задержки запросов

Если ClickHouse у вас живёт рядом с веб‑частью/дашбордами и нагрузка растёт, на практике помогает разнести роли и держать веб‑проекты на виртуальном хостинге, а базу — на отдельном сервере.

Виртуальный хостинг FastFox
Виртуальный хостинг для сайтов
Универсальное решение для создания и размещения сайтов любой сложности в Интернете от 95₽ / мес

Parts и SELECT: чеклист, что чинить первым

Когда в production «просел SELECT», не начинайте с тюнинга отдельных запросов. Сначала проверьте базовые контуры: parts, merges, диск, память.

  1. Сколько активных parts? Десятки тысяч на таблицу — уже повод разбираться, сотни тысяч — почти всегда причина деградации.

    clickhouse-client -q "SELECT table, count() AS parts FROM system.parts WHERE active AND database = currentDatabase() GROUP BY table ORDER BY parts DESC"
  2. Успевают ли merges? Если merges постоянно в работе, а parts продолжают расти — ищите проблему во вставках, диске или партиционизации.

  3. Есть ли конкуренция за диск? Heavy SELECT + heavy merges на одном диске обычно дают «пилу» по latency. Решения: ограничение параллелизма, вынос тяжёлых отчётов по расписанию, иногда разнос нагрузок по узлам.

  4. Хватает ли памяти запросам? Частые отмены по памяти и активный swap почти всегда означают, что лимиты/профили запросов и кэши настроены без запаса.

Мини-рукбук: что делать при инциденте «SELECT стал медленным»

Если нужно быстро восстановить качество сервиса, действуйте последовательно и фиксируйте наблюдения (время, таблицы, симптомы):

  1. Проверьте, не идёт ли «шторм merges» и не растёт ли число parts у ключевых таблиц.

  2. Посмотрите топ запросов по времени/памяти: это один «монстр» или системная деградация.

    clickhouse-client -q "SELECT query_duration_ms, read_rows, read_bytes, memory_usage, query FROM system.query_log WHERE type='QueryFinish' AND event_time > now() - INTERVAL 15 MINUTE ORDER BY query_duration_ms DESC LIMIT 10"
  3. Если память на грани — временно снизьте параллелизм тяжёлых запросов и ограничьте ресурсы проблемного пользователя/приложения (лучше точечно, чем глобально).

  4. Если причина в inserts/parts — приоритизируйте исправление пайплайна вставок (батчи, буферизация, пересмотр партиций). Иначе инцидент вернётся.

Что ещё полезно прокачать на VDS

Если ClickHouse работает рядом с веб‑частью (API/дашборды), полезно отдельно навести порядок с кэшированием на фронте/прокси, чтобы сгладить пики и снизить число тяжёлых запросов в базу. По смежной теме может пригодиться разбор про кэширование в PHP на Memcached и Redis.

Итоги

Производительность SELECT в ClickHouse на VDS почти всегда определяется тремя вещами: количеством parts (MergeTree), темпом и качеством background merges, и тем, как вы управляете памятью (лимиты max_memory_usage, механизмы overcommit и баланс кэшей mark/uncompressed cache). Держите эти контуры под контролем — и запросы станут предсказуемыми, а тюнинг отдельных SQL превратится в аккуратную настройку, а не борьбу с симптомами.

Поделиться статьей

Вам будет интересно

Linux sysctl и systemd-sysctl: ip_forward, rp_filter, tcp_tw_reuse и порядок override OpenAI Статья написана AI (GPT 5)

Linux sysctl и systemd-sysctl: ip_forward, rp_filter, tcp_tw_reuse и порядок override

Разбираем sysctl и systemd-sysctl на практике: где хранить параметры ядра, что важнее — /etc/sysctl.conf или sysctl.d, как работае ...
Linux: Port 22: Connection timed out — диагностика SSH по шагам (firewall, fail2ban, ss, tcpdump) OpenAI Статья написана AI (GPT 5)

Linux: Port 22: Connection timed out — диагностика SSH по шагам (firewall, fail2ban, ss, tcpdump)

Если SSH «висит» с Connection timed out на 22 порту, чаще виноваты сеть и фильтрация, а не пароль. Разбираем по шагам: проверка кл ...
VDS network troubleshooting: iperf3, mtr, ss и tcpdump — практический разбор OpenAI Статья написана AI (GPT 5)

VDS network troubleshooting: iperf3, mtr, ss и tcpdump — практический разбор

Пошаговый румбук для админов: как на VDS быстро локализовать сетевую проблему — низкую скорость, потери пакетов, высокий RTT, ретр ...