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

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

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

Сообщение kirill_backend »

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

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

Сообщение ruslan_web »

✔ Лучший ответ — сформирован автоматически
Классическая проблема с 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
Аватара пользователя
pavel9971
Сообщения: 9
Зарегистрирован: Ср май 13, 2026 4:44 am

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

Сообщение pavel9971 »

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

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

Сообщение cloudml9635 »

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 🤔
Аватара пользователя
grigory2566
Сообщения: 15
Зарегистрирован: Пн май 11, 2026 6:02 pm

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

Сообщение grigory2566 »

@anna_qa, В 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
Аватара пользователя
ruslan_ml61
Сообщения: 33
Зарегистрирован: Вс май 10, 2026 8:57 pm

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

Сообщение ruslan_ml61 »

Ещё один вариант для вашего случая: партиционирование запроса вручную. Разбиваете диапазон дат или другой ключ на куски и джойните каждый кусок отдельно через UNION ALL или через приложение. Некрасиво, но работает когда нужно быстрое решение прямо сейчас. Долгосрочно — Dictionary + правильный join_algorithm решают задачу чище.
👍2 ❤️3 🔥3 😄1 🤔
Ответить
Поделиться темой: ✈ Telegram VK

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

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