ClickHouse съедает всю память при сложных JOIN — как бороться?

Рейтинг: 84.6% · 53 голосов
SQL и NoSQL: PostgreSQL, MySQL, Redis, MongoDB, ClickHouse, ElasticSearch — проектирование схем, индексы, репликация и оптимизация запросов.
Ответить
Аватара пользователя
rburr
Сообщения: 77
Зарегистрирован: 12 май 2026, 17:53

ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение rburr »

Столкнулись с проблемой на ClickHouse 24.8 (LTS). Есть запрос с тремя JOIN: большая таблица событий (2 млрд строк) джойнится с двумя словарными таблицами (~10M строк каждая). При выполнении запроса ClickHouse съедает 180 GB RAM из доступных 256 GB и либо OOM-кидает, либо начинает свопировать и запрос идёт 40 минут. Без JOIN тот же запрос — 8 секунд. Как правильно настроить JOIN в ClickHouse чтобы не взрывать память?
👍2 ❤️2 🔥2 😄 🤔2
✔ Лучший ответ сформирован автоматически — Bowden
Классическая проблема с hash join на большом build side. Первое что нужно сделать — явно указать алгоритм: SET join_algorithm = 'partial_merge'; Это переключает на merge join который работает с диском и не держит всё в памяти. Да, будет медленнее чем hash join, но не упадёт. Второй вариант: SET join_algorithm = 'auto'; — ClickHouse сам выберет алгоритм исходя из размера. С версии 23.x это…
Перейти к ответу →
Аватара пользователя
Bowden
Сообщения: 80
Зарегистрирован: 12 май 2026, 09:21

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение Bowden »

✔ Лучший ответ — сформирован автоматически
Классическая проблема с hash join на большом build side. Первое что нужно сделать — явно указать алгоритм: SET join_algorithm = 'partial_merge'; Это переключает на merge join который работает с диском и не держит всё в памяти. Да, будет медленнее чем hash join, но не упадёт. Второй вариант: SET join_algorithm = 'auto'; — ClickHouse сам выберет алгоритм исходя из размера. С версии 23.x это работает достаточно хорошо.

Ещё очень помогает правильный порядок таблиц в JOIN: большая таблица всегда слева (она становится probe side), маленькая справа (build side). ClickHouse не всегда сам переставляет таблицы как PostgreSQL, порядок важен.
👍4 ❤️1 🔥2 😄 🤔1
Аватара пользователя
roman2026
Сообщения: 39
Зарегистрирован: 10 май 2026, 23:40

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение roman2026 »

Для словарных таблиц (10M строк — это как раз словарь) используйте Dictionary в ClickHouse вместо обычного JOIN. Создаёте Dictionary с layout HASHED или FLAT, и вместо JOIN пишете dictGet('my_dict', 'column_name', id). Словарь живёт в памяти отдельно, кэшируется, и запрос превращается из JOIN в простой lookup. У нас это убрало 90% проблем с памятью на аналитических запросах.
👍3 ❤️1 🔥2 😄1 🤔
Аватара пользователя
regexveteran
Сообщения: 34
Зарегистрирован: 12 май 2026, 03:09

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение regexveteran »

max_bytes_in_join и max_rows_in_join — ваши друзья. Поставьте лимит и ClickHouse упадёт с внятной ошибкой вместо того чтобы тихо свопировать:

SET max_bytes_in_join = 10000000000; -- 10 GB
SET join_overflow_mode = 'throw';

Когда будете знать точный размер build side — можно поднять лимит осознанно. Ещё проверьте join_use_nulls, иногда включение добавляет лишний overhead.
👍1 ❤️6 🔥1 😄1 🤔
Аватара пользователя
vaultaddict
Сообщения: 10
Зарегистрирован: 11 май 2026, 20:49

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение vaultaddict »

@Bowden, В ClickHouse 2026 появился cost-based join reordering и parallel hash join по умолчанию — это реально меняет картину. Если вы на 24.8 LTS — попробуйте обновиться до последнего стабильного (сейчас 25.x). Parallel hash join использует несколько потоков для построения hash table и значительно снижает пиковую память за счёт параллелизма. По нашим тестам на похожей нагрузке память упала с 160 GB до 90 GB просто от обновления.
👍3 ❤️5 🔥2 😄3 🤔1
Аватара пользователя
eelvis
Сообщения: 6
Зарегистрирован: 24 май 2026, 11:33

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение eelvis »

Ещё один вариант для вашего случая: партиционирование запроса вручную. Разбиваете диапазон дат или другой ключ на куски и джойните каждый кусок отдельно через UNION ALL или через приложение. Некрасиво, но работает когда нужно быстрое решение прямо сейчас. Долгосрочно — Dictionary + правильный join_algorithm решают задачу чище.
👍2 ❤️3 🔥3 😄1 🤔
Аватара пользователя
async2025
Сообщения: 44
Зарегистрирован: 13 май 2026, 02:57

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение async2025 »

@regexveteran, Dictionary — однозначно правильное направление для словарей 10M строк. Но важная деталь: если словарь обновляется часто (чаще раза в час), layout HASHED с lifetime означает, что во время reload ClickHouse держит две копии словаря одновременно — старую и новую. На 10M строк это лишние ~2-4 GB RAM в момент перезагрузки. Для больших словарей лучше смотреть на CACHE layout или разбивать reload через LIFETIME min/max с джиттером, чтобы не всё одновременно переливалось.
👍 ❤️1 🔥 😄 🤔
Аватара пользователя
cordoba
Сообщения: 14
Зарегистрирован: 16 май 2026, 05:44

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение cordoba »

Ещё момент который в треде не упомянули: порядок таблиц в JOIN в ClickHouse критичен. Большая таблица должна быть слева (она стримится), маленькая справа (она идёт в hash table). Если вы пишете JOIN наоборот — вы загоняете 2 млрд строк в память. Проверьте EXPLAIN для своего запроса, там будет видно что идёт в build side. Иногда простой swap таблиц в запросе без каких-либо SET решает проблему в разы лучше любых настроек алгоритма.
👍 ❤️1 🔥 😄 🤔
Аватара пользователя
seniorsamurai
Сообщения: 44
Зарегистрирован: 15 май 2026, 19:29

Re: ClickHouse съедает всю память при сложных JOIN — как бороться?

Сообщение seniorsamurai »

@eelvis, про партиционирование вручную — если идти этим путём, то через clickhouse-client с --parallel_replicas или просто через приложение с пулом параллельных запросов по диапазонам дат можно ещё и времени сэкономить. У нас был похожий кейс: разбили на 30 ежедневных кусков, запустили параллельно, результат UNION ALL на уровне приложения — общее время 40 минут превратилось в 3 минуты за счёт параллелизма, а память на каждый запрос в норме.
👍2 ❤️ 🔥1 😄1 🤔
Ответить
Поделиться темой: ✈ Telegram VK
Похожие запросы: clickhouse vs postgresql для аналитики что выбратькак посмотреть сколько памяти занято в linuxoom killer кто убил процесс linux как узнатькак понять что съедает память на сервере linux

Вернуться в «Базы данных»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость