BI Consult Desktop Logo BI Consult Mobile Logo
  • Russian BI Исследование российских bi
  • Перейти на Fine BI
  • Контакты
  • +7 812 334-08-01
    +7 499 608-13-06
  • Отправить сообщение
  • Главная
  • Продукты Эксперт-BI
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Сельское хозяйство
    • Энергетика
    • FMCG
    • Девелоперы
    • Маркетплейсы
    • Пищевая промышленность
    • Фармацевтика
    • Построение Data Platform
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и FP&A
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • IBP
    • ИТ (CIO)
    • Закупки
  • Платформы
    • Системы бизнес-анализа (BI)
    • Интегрированное бизнес-планирование (IBP)
    • Хранилища данных (DWH / Lakehouse)
    • Каталоги данных (Data Catalog)
    • Системы ETL и ELT
    • AI / Исскуственный интеллект
    • Шина данных (ESB)
    • Система управления мастер-данными (MDM)
    • Семантический слой
  • Услуги
    • Переход на отечественные BI и DWH системы
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений и DWH
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Курсы
    • Учебный курс Информационная грамотность (Data Literacy)
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Greenplum
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt (Data Build Tool)
  • Компания
    • Руководство
    • Новости
    • Клиенты
    • Карьера
    • Скачать
    • Контакты

BI

  • FineBI
  • FineReport
  • FineDataLink
  • FineChatBI (FineAI)
  • Коннекторы данных из 1С в BI
  • Airflow / Nifi
  • Visiology
  • PIX BI
  • Modus BI
  • Yandex.DataLens
  • Open-source BI: Superset/Metabase
  • Luxms BI
  • AW BI + Alpha BI
  • FlyBI + Форсайт. Аналитическая Платформа
  • Loginom
  • Триафлай
  • AI / Исскуственный интеллект
  • Optimacros
  • Навигатор BI
  • Семантический слой

СУБД

  • Arenadata
  • ClickHouse
  • Greenplum
  • Postgres Professional
  • TData

Другое

  • Построение Data Platform
    • Аналитическое хранилище данных
    • Data Lake и Data Engineering
    • Подробнее про Data Lake
    • Внедрение Lakehouse
      • Apache Doris
      • StarRocks
      • Trino
    • Миграция витрин из пропиетарных DWH на новый стек
    • Учебный курс "Современная архитектура хранилища данных"
Главная » Курсы по системам бизнес-анализа и методологии » Учебный курс по ClickHouse » Тонкости агрегации в ClickHouse_ как избежать OOM-ошибки с GROUP BY

Тонкости агрегации в ClickHouse_ как избежать OOM-ошибки с GROUP BY

Ошибки Out Of Memory (OOM) в аналитических запросах на ClickHouse чаще всего возникают при выполнении агрегирования с GROUP BY. Причины лежат в самой природе задачи: для вычисления агрегатных функций по группам система должна одновременно хранить в памяти либо все группы, либо значительную их часть, вместе с промежуточными состояниями агрегатов. В колоночных СУБД это реализуется через специализированные хэш-таблицы, которые быстро растут как по числу записей, так и по размеру каждой записи при увеличении длины ключа и объемности состояния агрегатов. Несвоевременная выгрузка на диск, неоптимальная модель выполнения или неправильный выбор агрегатных функций усугубляют проблему.

Цель данной статьи - системно разобрать, как работает GROUP BY в ClickHouse, почему и когда он потребляет много памяти, и какие инженерные подходы, настройки и паттерны проектирования помогают предотвратить OOM без недопустимого ущерба для производительности и точности. Мы пойдем от принципов колоночных агрегаций к деталям реализации в ClickHouse, разберем компромиссы и приведем практические кейсы.

 

Теоретические основы агрегирования и группировки данных в колоночных СУБД

Колоночные СУБД ориентированы на аналитические нагрузки: данные хранятся по столбцам, что позволяет эффективно сжимать и читать только нужные поля. Однако агрегация всегда требует логического объединения строк в группы по ключу и вычисления состояний агрегатов поверх каждой группы. В терминах вычислительных моделей ключевые аспекты таковы:

  • Модель данных: группировка основана на значениях ключа (одно или несколько выражений), по каждому уникальному ключу формируется отдельное состояние агрегатов.
  • Состояние агрегата: промежуточные структуры, поддерживаемые для инкрементального обновления (например, сумма, количество, статистики квантилей), которые затем финализируются в итоговое значение.
  • Стратегии выполнения: хэш-агрегация (in-memory hash aggregation), агрегация по порядку (streaming по ключу сортировки), внешняя агрегация (со сбросом на диск), а также гибридные схемы.
  • Ограничения ресурсов: пиковое потребление RAM задается количеством одновременных групп и размером состояния на группу, с учетом накладных расходов хэш-таблиц и фрагментации.

Ключевой компромисс: скорость против памяти и точности. Хэш-агрегация быстра, но требует RAM; агрегация «в порядке» экономит память, но может замедлять запросы; внешний spill на диск снижает риск OOM, но увеличивает задержки ввиду IO.

 

Модель выполнения GROUP BY в ClickHouse: этапы, ограничения и семантика

ClickHouse реализует многопоточную хэш-агрегацию с рядом оптимизаций:

  1. Построение локальных хэш-таблиц на потоках. Каждому потоку соответствует как минимум одна неблокирующая хэш-таблица, куда инкрементально вносятся ключи и состояния агрегатов.
  2. Разбиение на блоки и параллельное слияние. Для масштабирования слияния ClickHouse использует 256-блочную разбивку (по одному байту хэша ключа), позволяя выполнять последующее слияние параллельно.
  3. Финализация. На завершающем этапе состояния агрегатов преобразуются в результирующие значения, формируется итоговый набор строк.

Ограничения и следствия:

  • Память расходуется пропорционально количеству уникальных ключей и размеру агрегатных состояний.
  • В отличие от DISTINCT/LIMIT BY, агрегирование завершает работу только после обработки всего входа (если не задействована агрегация в порядке с ранним выводом).
  • В распределенных запросах существенной может стать нагрузка на сервер-инициатор, если не включен «память-эффективный» режим распределенной агрегации.

Семантически GROUP BY диктует, что каждое выражение в SELECT/HAVING/ORDER BY либо является частью ключа группировки, либо вычисляется на агрегатах по сгруппированным данным.

 

Агрегатные функции: стандартные и специфичные для ClickHouse, области применимости

ClickHouse поддерживает как стандартные агрегатные функции (count, min, max, sum, avg, any, stddevPop, stddevSamp, varPop, varSamp, covarPop, covarSamp), так и обширную линейку специализированных:

  • Точные, потенциально «тяжелые» по памяти: uniqExact, quantileExact/medianExact, groupArray (без ограничения), функции на базе карт/массивов, sequenceMatch/sequenceCount, windowFunnel, groupBitmap.
  • Приближенные, ресурсоэффективные: uniqCombined, uniqHLL12, quantileTDigest, quantileTiming/quantileDeterministic (по ситуации), разнообразные комбинированные функции.

Выбор агрегатов - один из ключевых рычагов предотвращения OOM. Например, quantileExact хранит полный набор значений в состоянии и потому масштабируется плохо, тогда как quantileTDigest аппроксимирует распределение в компактной структуре. Аналогично uniqExact требует хранения точного множества, а uniqCombined и HLL-варианты - скетчи с контролируемой ошибкой.

 

Семантика выражений в SELECT, HAVING и ORDER BY при агрегации

Правило строгое: любой столбец исходной таблицы, присутствующий в SELECT, должен быть либо:

  • частью ключа группировки (перечислен в GROUP BY или является детерминированной функцией от такого ключа), либо
  • аргументом агрегатной функции.

 

HAVING фильтрует уже агрегированные строки по итоговым значениям агрегатов и/или выражениям на ключах. ORDER BY может опираться на ключи и результаты агрегатов. В противном случае запрос логически не определен: невозможно вывести «сырое» поле для нескольких строк, если они сведены в одну группу.

 

Кардинальность групп и объем результата: от пустого набора ключей до уникальных значений

Агрегация может радикально уменьшить объем результата - при небольшой кардинальности ключей группировки. Однако возможны и крайние случаи:

  • Пустой набор ключей (агрегация «по всему набору»): всегда возвращает одну строку. Это часто используется для глобальных метрик.
  • Ключ высокой кардинальности (все значения уникальны): число строк результата совпадет с числом строк исходных данных; память при этом растет почти линейно с объемом входа.

Практический эффект на память определяется не только числом групп, но и:

  • размером ключа (String/UUID/комбинированные ключи против компактных UInt32/UInt64),
  • суммарным размером состояний агрегатов на группу,
  • коэффициентом загрузки и накладными расходами хэш-таблиц.

 

Подытоги и многомерная агрегация: модификаторы WITH ROLLUP, CUBE, TOTALS

ClickHouse поддерживает расширения для многомерной аналитики:

  • WITH ROLLUP добавляет к результату иерархические подытоги, последовательно агрегируя по префиксам ключа.
  • WITH CUBE вычисляет все комбинации подытогов для заданного набора измерений, что экспоненциально увеличивает число строк.
  • WITH TOTALS возвращает дополнительную строку общих итогов по всем данным запроса.

Эти модификаторы удобны, но требуют аккуратности: при высокой размерности измерений CUBE и ROLLUP могут умножить объем состояния и времени выполнения. На больших датасетах их целесообразно применять к предварительно агрегированным данным.

 

Обработка NULL в ClickHouse: особенности и последствия для агрегирования

ClickHouse трактует NULL (в Nullable-типах) при группировке как обычное значение - все NULL попадают в одну и ту же группу. Это согласуется с практикой многих аналитических движков и важно для интерпретации результатов: отсутствие значения становится отдельной категорией. Следует помнить о явных приведениях типов и функциях обработки NULL (например, coalesce-подобные приемы), чтобы избежать паразитного раздувания кардинальности из-за неоднородности представлений пропусков.

 

Декомпозиция технических компонентов: хэш-таблицы, их специализации и распределение по потокам

Ядро GROUP BY - специализированные хэш-таблицы. В ClickHouse доступны десятки специализаций, автоматически подбираемых по типам ключей:

  • Для числовых ключей - компактные и быстрые структуры с сохранением хэша.
  • Для строк - варианты со «сохраненным хэшем» и оптимизациями для коротких/длинных строк.
  • Для составных ключей - структуры, учитывающие пакетирование нескольких полей.

 

Важные факторы потребления памяти:

  • размер ключа (fixed-size типы предпочтительнее длинных строк),
  • размер состояния агрегатов,
  • оверхед элементов таблицы (ссылки, выравнивание, хэш, фактор заполнения).

ClickHouse использует неблокирующие (lock-free) структуры для вставки в хэш-таблицы, что устраняет межпоточные блокировки, но требует последующего слияния.

 

Многопоточная агрегация: неблокирующие структуры, 256-блочная разбивка и параллельное слияние

Чтобы распараллелить дорогостоящий этап слияния локальных таблиц, используется двухуровневая схема с 256-блочной разбивкой. Смысл в том, что каждое состояние попадает в один из 256 «карманов» по одному байту хэша ключа; это дает:

  • независимое, параллельное слияние по карманам на нескольких потоках,
  • возможность внешней агрегации по блокам (spill на диск),
  • более предсказуемое пиковое потребление RAM (достаточно уместить по одному блоку на поток при внешней агрегации).

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

 

Проектирование ключа группировки: типы данных, размер ключа и кардинальность

Правильно спроектированный ключ - самый действенный способ экономии памяти:

  • Сокращайте размер ключа. Вместо длинных строк используйте суррогатные целые идентификаторы (UInt32/UInt64), хэши фиксированного размера или словарное кодирование на этапе подготовки данных.
  • Контролируйте кардинальность. Неинформативные измерения с экстремально высокой уникальностью (например, временные метки до наносекунд в ключе) резко раздувают память.
  • Используйте инъективные преобразования осознанно. Инъективная функция от сортировочного ключа (например, стабильное хэширование фиксированной длины) может помочь задействовать агрегацию «в порядке» и сэкономить RAM.
  • Формируйте составные ключи экономно. Каждое дополнительное поле в ключе - кратный рост числа групп и состояния.

Практика: перенос части измерений в последующий JOIN к агрегированному результату иногда выгоднее, чем группировать сразу по широкому ключу.

 

Внешняя агрегация и работа с диском: блоки, пороги, требования к памяти

Когда оперативной памяти не хватает, ClickHouse может выполнять внешнюю агрегацию - выгружать промежуточные блоки на диск с последующим слиянием:

  • Сброс производится по достижении порога памяти, настроенного пользователем.
  • Данные пишутся по карманам (из 256), что уменьшает число пересечений при чтении и слиянии.
  • Требуется достаточное дисковое пространство и пропускная способность. Важна конфигурация временного хранилища (SSD заметно лучше HDD).

Следствие: для устойчивости системы под высокой конкуррентной нагрузкой следует планировать емкость временного хранилища и мониторить объем spill.

 

Оптимизация в порядке сортировки: настройка optimize_aggregation_in_order и ее компромиссы

Если источник данных уже отсортирован по ключу группировки (или по инъективной функции от него), ClickHouse может агрегировать потоково: при смене ключа промежуточное состояние финализируется и выводится, не накапливая все группы в памяти. Включение механизма управляется настройкой optimize_aggregation_in_order.

Компромиссы:

  • Плюс: резкое снижение пикового потребления RAM** - часто на порядки.
  • Минусы: ухудшение степени параллелизма чтения и возможное увеличение общего времени выполнения; требования к учебку «в нужном порядке» (реалистично при MergeTree-партиционировании и подходящем ключе сортировки).

Эта оптимизация особенно эффективна для запросов по узкому окну данных, когда порядок чтения по ключу легко обеспечить.

 

Управление памятью: max_bytes_before_external_group_by, max_memory_usage и стратегия двух этапов

Ключевые настройки для предотвращения OOM:

  • max_bytes_before_external_group_by - порог памяти, при достижении которого включается внешний spill для агрегирования. По умолчанию 0 (spill выключен).
  • max_memory_usage - общий лимит памяти на запрос.

Практическая стратегия: задавайте max_memory_usage примерно вдвое больше max_bytes_before_external_group_by. Обоснование - агрегация проходит в два этапа: на этапе 1 возможен сброс на диск; на этапе 2 потребление может приблизиться к объему этапа

  1. Если порог равен X, то лимит разумно выставить около 2X. На практике пик RAM чуть больше X при активном spill.

Наряду с лимитами важно выбрать директорию/диск для временных данных и контролировать их доступный объем, поскольку превышение емкости временного хранилища приведет к ошибкам и повторному OOM уже на диске.

 

Распределенная агрегация: distributed_aggregation_memory_efficient и баланс нагрузки на инициаторе

В распределенных запросах сервер-инициатор часто становится «узким местом»: именно он собирает и сливает частичные результаты от удаленных шардов. Для снижения пикового потребления RAM и давления на инициатор включается режим distributed_aggregation_memory_efficient.

Семантика эффекта:

  • Часть работы по агрегации и локальному слиянию переносится на удаленные узлы.
  • На инициатор передаются более компактные представления состояний и/или данные блоками, что уменьшает его пиковое потребление памяти.
  • Возможен рост сетевого трафика или числа этапов слияния; в большинстве сценариев это справедливая цена за отказоустойчивость по памяти.

Грамотный тюнинг этого режима - стандартная практика на кластерах с большими шардовыми наборами и запросами высокой кардинальности.

 

Ограничивающие и ресурсоемкие агрегаты: groupArray, uniqExact, quantileExact, windowFunnel, groupBitmap, sequenceMatch/Count, Map

Некоторые агрегаты по своей природе склонны к неограниченному росту состояния:

  • groupArray - без параметра-ограничителя сохраняет все элементы группы; безопаснее использовать groupArray(N) с верхней границей.
  • uniqExact - точный подсчет уникальных требует хранения всех наблюденных значений.
  • quantileExact/medianExact - точные квантили хранят выборку; масштабируются плохо.
  • windowFunnel - модели воронок/последовательностей могут требовать массивов событий на группу.
  • groupBitmap - Roaring Bitmap в среднем эффективен, но при экстремальной дисперсии идентификаторов и высокой кардинальности ключей может стать дорогим по памяти.
  • sequenceMatch/sequenceCount - конечные автоматы с потенциально большим количеством промежуточных состояний.
  • Агрегаты, накапливающие Map/Array без ограничения, - источник неограниченного роста.

Рекомендации: ограничивать размеры (параметры), заменять на приближенные аналоги, выполнять такие агрегаты на поздней стадии после предварительного сокращения кардинальности, использовать материализованные представления для частичной агрегации.

 

Приближенные агрегаты и компромисс точность-ресурсы: uniqCombined, quantileTDigest и альтернативы

Приближенные методы позволяют удержать память под контролем:

  • uniqCombined/uniqHLL12 - скетч-подсчеты с заранее известной ошибкой и компактной памятью.
  • quantileTDigest - структура t-digest сохраняет сжатый профиль распределения; подойдет для больших выборок с контролируемой погрешностью.
  • Гибридные пайплайны - точная агрегация на «узком» слое (например, в партиции/шарде/окне), а затем объединение приближением.

Ключевой принцип: согласуйте допустимую погрешность с бизнес-требованиями. Часто 0.5-2% отклонения в метрике окупает кратное снижение RAM и времени.

 

Диагностика и профилирование: send_logs_level='trace', EXPLAIN, системные логи и трассировка

Для анализа «почему запрос потребляет так много памяти» полезны следующие инструменты:

  • send_logs_level='trace' - детальная трассировка с этапами агрегации, переходом к двухуровневой схеме, сообщениями о spill.
  • EXPLAIN (PLAN/PIPELINE/AST) - понимание физического плана, числа потоков, границ между этапами, наличия внешней агрегации и слияний.
  • Системные логи и таблицы: system.query_log, system.query_thread_log, system.text_log, system.trace_log - дают профиль памяти, время по стадиям, коды ошибок, исключения OOM.
  • Мониторинг ОС и дисковой подсистемы - подтверждает факт spill, скорость чтения/записи, очереди на диск.

Полезная техника: поочередно упрощать запрос, убирая «подозрительные» агрегаты и расширения (ROLLUP/CUBE), чтобы локализовать главный потребитель RAM.

 

Метрики эффективности и наблюдаемость: RAM, spill-объемы, кардинальность, время, CPU/IO

Система наблюдения должна включать как минимум следующие метрики:

  • Пиковое и среднее потребление RAM на запрос и в целом по серверу.
  • Объем и скорость внешнего spill (количество и суммарный размер временных файлов).
  • Оценки кардинальности групп (в логах/диагностике и на уровне доменной модели).
  • CPU: доля времени на вставку в хэш-таблицы и на слияние.
  • IO: пропускная способность и очереди диска в фазах spill/merge.
  • Время по основным стадиям: чтение, агрегация (build), слияние (merge), финализация.

Наблюдаемость должна быть сквозной: от приложения/BI-инструмента до планировщика и СУБД, чтобы видеть влияние concurency и всплесков нагрузки.

 

Паттерны проектирования запросов и данных: предварительная агрегация, сужение ключей, инъективные преобразования

Эффективность достигается на уровне модели данных и запросов:

  • Предварительная агрегация. Материализованные представления на базе AggregatingMergeTree/ SummingMergeTree хранят состояния/суммы и позволяют выполнять тяжелые GROUP BY инкрементально при загрузке.
  • Сужение ключей. Заменяйте широкий ключ на суррогат; выносите «широкие» атрибуты в справочники (JOIN после агрегации).
  • Инъективные функции и сортировка. Проектируйте сортировочные ключи таблиц так, чтобы запросы могли использовать optimize_aggregation_in_order.
  • Фильтрация раньше агрегации. Максимально узкое WHERE/ PREWHERE снижает объем входа и, соответственно, число групп.

Эти паттерны системно уменьшают риск OOM и стабилизируют латентность.

 

Кейсы из практики: предотвращение OOM при высокой кардинальности и больших ключах

Кейс 1: Логи веб-событий с user_id как строкой длиной 36 (UUID-строка). Запросы с GROUP BY user_id регулярно упирались в OOM.

Решение: заменить строковый user_id на бинарный UUID (FixedString(16)) и далее на UInt128/два UInt64; включить внешнюю агрегацию с порогом и перейти на quantileTDigest для процентовилей. Итог - 3-5-кратное снижение RAM, устранение OOM.

Кейс 2: Подсчет uniqExact по session_id на суточном окне в распределенном кластере.

Решение: включить distributed_aggregation_memory_efficient, на шардовом уровне считать uniqHLL12, а на инициаторе объединять скетчи; итоговая ошибка <1%, стабильность под пиками нагрузки.

Кейс 3: Воронка действий (windowFunnel) по широкому ключу (пользователь + кампания + устройство).

Решение: предварительная агрегация по (пользователь, кампания) с ограничением groupArray(N) для событий, затем windowFunnel на «суженном» результате; исключение «устройства» из ключа и перенос его в постагрегационный анализ. Результат - снижение времени в 2.7 раза, RAM в 4 раза.

 

Интеграция технологических стеков: ClickHouse с Apache NiFi, Kafka и Spark для устойчивых агрегаций

Интеграция потоковых платформ помогает перераспределить нагрузку:

  • Kafka: перенос части агрегаций в стриминг-слой (например, подсчет уникальных по скетчам на партициях), публикация в компактном виде для ClickHouse.
  • Apache NiFi: реализация фильтрации, нормализации и обогащения до записи; уменьшение ширины ключа на входе в DWH.
  • Apache Spark/Flink: предварительные суточные/часовые агрегации на HDFS/объектном хранилище, загрузка в ClickHouse как агрегированных слоев; для точных расчетов - последующий «додосчет» на малом объеме.

Такая архитектура снижает пиковые требования к памяти и диску в момент BI-запросов и ослабляет зависимость SLA от разовых всплесков кардинальности.

 

Сценарии применения в отраслях: финтех, e-commerce, телеком, AdTech, IoT-аналитика

  • Финтех: антифрод с квантилями задержек и аномалиями по клиентам. Решение - t-digest и предварительные агрегаты по окнам.
  • E-commerce: сегментация покупателей и RFM-аналитика. Решение** - surrogate keys, агрегаты в материальных представлениях, rollup по категориям.
  • Телеком: корреляция событий сети по ячейке/частоте/времени. Решение - optimize_aggregation_in_order на совпадающих сортировочных ключах, внешний spill при больших окнах.
  • AdTech: подсчет уникальных показов/кликов с очень высокой кардинальностью. Решение - uniqCombined/uniqHLL12, распределенная память-эффективная агрегация.
  • IoT: агрегирование телеметрии по устройствам/датчикам. Решение - ограничение groupArray, сглаживание и расчет приближенных квантилей на уровне шардов.

 

Анализ рисков, уязвимостей и ограничений: SLA, емкостное планирование и операционные компромиссы

Основные риски:

  • Непредсказуемые пики кардинальности (новые кампании, «бурсты» устройств).
  • Рост состояния из-за «тяжелых» агрегатов и широких ключей.
  • Переполнение временного хранилища при массовом spill.

Управленческие меры:

  • Емкостное планирование RAM/диска с запасом по профилю нагрузок; квотирование по ролям/проектам.
  • Политики запросов: валидация, лимиты ресурсов, запрет на точные агрегаты в онлайне при экстремальных объемах.
  • Отдельные пулы для «эксплорерских» запросов и продуктивных дашбордов; канареечные деплойменты настроек.

Компромисс: лучше чуть медленнее, но предсказуемо и без OOM, чем «супербыстро» иногда и «падает» на пиках.

 

Конкурентный анализ: стратегии GROUP BY и управления памятью в альтернативных системах

  • Trino/Presto: хэш-агрегация с возможностью spill на диск; похожие компромиссы скорость/RAM, но слабее интеграция с колоночными индексами хранения.
  • Spark SQL: планировщик с внешней агрегацией и проектом Tungsten для управления памятью; хорош для batch-объемов, менее эффективен для интерактива.
  • Druid/Pinot: сегментно-ориентированная архитектура, инкрементная агрегация на ingestion; хороши для OLAP-дашбордов с заранее подготовленными агрегатами.
  • BigQuery/Snowflake: серверлесс и автоматическое масштабирование с «прозрачным» spill на собственную инфраструктуру; однако контроль детализированных настроек ограничен.

ClickHouse сильнее там, где требуется тонкая подстройка и предсказуемый контроль ресурсов при высоких скоростях на собственном железе.

 

Чек-лист настроек и практик для безопасных и быстрых GROUP BY

  • Включите внешний spill для агрегирования: установите разумный max_bytes_before_external_group_by и соотнесите max_memory_usage ≈ 2× порога.
  • Задумайтесь о optimize_aggregation_in_order для запросов, которые могут читать данные в соответствии с сортировочным ключом.
  • Для распределенных запросов включите режим памяти на инициаторе: distributed_aggregation_memory_efficient.
  • Минимизируйте размер ключей (суррогаты, UUID как binary/числовой тип, избегайте длинных строк).
  • Заменяйте точные «тяжелые» агрегаты на приближенные, лимитируйте groupArray(N).
  • Используйте предварительную агрегацию (материализованные представления) и фильтрацию до агрегирования.
  • Профилируйте запросы: send_logs_level='trace', EXPLAIN PIPELINE/PLAN, системные логи.
  • Мониторьте RAM, объем spill, кардинальность и IO; планируйте емкость временного хранилища.

 

Заключение: баланс скорости, потребления памяти и точности при агрегировании в ClickHouse

Предотвращение OOM при GROUP BY в ClickHouse - это не одна «волшебная настройка», а системная инженерная дисциплина. На архитектурном уровне - минимизация кардинальности и размера ключей, осознанный выбор агрегатов (часто приближенных), подготовка данных и сортировочных ключей. На уровне исполнения - агрегация «в порядке», внешние spill и память-эффективная распределенная схема. На уровне эксплуатации - прозрачная наблюдаемость, лимиты и практики емкостного планирования.

Ключевой вывод прост и практичен: чем раньше вы уменьшите количество групп и размер их состояний, тем меньше риск OOM и выше стабильность. А там, где точность вторична, - приблизительные структуры и предварительные агрегаты дают наилучшее соотношение цена/качество. При грамотной комбинации этих подходов ClickHouse стабильно выдерживает самые агрессивные GROUP BY даже на экстремальных объемах.

Вопрос-Ответ:

  • Вопрос: Почему GROUP BY в ClickHouse часто «съедает» всю память?
    Ответ: Память расходуется хэш-таблицами, где на каждую уникальную группу хранится ключ и состояния агрегатов. Рост кардинальности и «тяжелых» агрегатов быстро увеличивает объем RAM.

  • Вопрос: Когда имеет смысл включать optimize_aggregation_in_order?
    Ответ: Когда источник можно читать в порядке ключа группировки (или инъективной функции от него). Это резко уменьшает память, но может замедлить запрос из-за меньшего параллелизма.

  • Вопрос: Как правильно настроить max_bytes_before_external_group_by и max_memory_usage?
    Ответ: Установить порог spill (X) и задать max_memory_usage примерно 2X. Это учитывает двухэтапную природу агрегации и предотвращает OOM на этапе финализации.

  • Вопрос: Какие агрегатные функции опаснее всего для памяти?
    Ответ: groupArray без лимита, uniqExact, quantileExact/medianExact, windowFunnel, groupBitmap в «плохих» распределениях, sequenceMatch/Count и любые, накапливающие неограниченные Map/Array.

  • Вопрос: Чем заменить точные «тяжелые» агрегаты?
    Ответ: Использовать uniqCombined/uniqHLL12 для уникальных, quantileTDigest для квантилей, а также ограничивать размеры (groupArray(N)) и выносить агрегацию на предварительные этапы.

  • Вопрос: Как распределенная настройка distributed_aggregation_memory_efficient помогает избежать OOM?
    Ответ: Переносит часть слияния и агрегации на удаленные шарды, снижая пиковую память на инициаторе; итогом становится более предсказуемое поведение под нагрузкой.

  • Вопрос: Что дает 256-блочная разбивка в многопоточной агрегации?
    Ответ: Независимое параллельное слияние и возможность эффективного внешнего spill по карманам, что уменьшает RAM и ускоряет финальную фазу объединения.

  • Вопрос: Какие паттерны проектирования данных наиболее эффективны против OOM?
    Ответ: Сужение ключей (суррогаты вместо строк), предварительная агрегация (материализованные представления), фильтрация до агрегирования и проектирование сортировочных ключей под агрегацию «в порядке».

← Предыдущая статья
Проекции в ClickHouse: теория, архитектура, реализация, мониторинг и применение в аналитике
Следующая статья →
Транзакции в ClickHouse

 

Узнать стоимость решенияЗапросить видео презентацию

Запросить видео презентацию Запросить доступ к демо стенду online Узнать стоимость лицензий

Задать вопрос

loading...

Решения

Анализировать ФинансыУвеличивайте ПродажиОптимальный Склад и ЛогистикаМаркетинговые Метрики

Клиенты
  • С объединением компании Savencia Fromage & Dairy и молочного комбината в г.Белебей, одного из лидеров по производству твердых сычужных сыров в России, Savencia выходит на российский рынок не только как импортер, но и как производитель молочной продукции.

  • Нашей компанией был реализован проект автоматизации конвейера данных на базе СПО ETL-инструмента Apache NiFi для клиента ООО «Императорский Монетный Двор» в части актуализации данных, передаваемых из Системы Oracle в Anaplan.

  • «Лента» – первая по величине сеть гипермаркетов и четвертая среди крупнейших розничных сетей страны. Компания была основана в 1993 г. в Санкт-Петербурге.

    «Лента» управляет 249 гипермаркетами в 88 городах России и 131 супермаркетом в Москве, Санкт-Петербурге, Сибири, Уральском и Центральном регионах с общей торговой площадью около 1 494 тыс. кв. м. Средняя торговая площадь одного гипермаркета «Лента» составляет около 5 500 кв.м, средняя площадь супермаркета – 800 кв.м. Компания оперирует двенадцатью распределительными центрами. Штат компании – около 50, 5 тыс. человек.

  • Торгово-производственному холдингу ТБМ, специализирующемуся на поставке комплектующих и фурнитуры для производства окон, дверей, стеклопакетов и мебели, был необходим аналитический инструмент для выявления узким мест и поиска зон роста бизнеса и, как результат, оптимизации процессов. Добиться этого можно было, только внедрив data-driven подход.

  • Решения
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Энергетика
    • Фармацевтика
  • Услуги
    • Переход на отечественные BI и DWH
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Техническая поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Платформы
    • FineBI
    • FineReport
    • FineDataLink
    • Коннекторы данных из 1С в BI
    • Airflow + NiFi
    • Visiology
    • Luxms BI
    • Modus BI
    • PIX BI
    • Arenadata
    • ClickHouse
    • Greenplum
    • Postgres Professional
    • Open-source BI: Superset/Metabase
    • Loginom
    • Yandex.DataLens
    • AI / Исскуственный интеллект
    • Optimacros
    • Шины данных
  • Курсы
    • Учебный курс Информационная грамотность
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt
  • Функциональные решения
    • Создание Data Lake
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и прогнозная аналитика
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • Сквозная аналитика
  • Компания
    • О нас
    • Руководство
    • Новости
    • Клиенты
    • Скачать
    • Контакты
    • Политика конфиденциальности
RutubeVkontakteLinkedInYouTube
ООО "Би Ай Консалт",
ИНН: 7811437757,
ОГРН: 1097847154184
199178, Россия,
Санкт-Петербург,
6-ая линия В.О., Д. 63, 4 этаж
Тел: +7 (812) 334-08-01
Тел: +7 (499) 608-13-06
E-mail: info@biconsult.ru

 

 

 

 

 

×

Пользуясь сайтом, вы соглашаетесь с использованием cookies и политикой конфиденциальности.