Привет! Меня зовут Андрей Дорожкин, и я руковожу командой администрации баз данных в Hybrid. В этом материале я поделюсь опытом работы с ClickHouse — колоночной БД, разработанной специально для аналитических запросов, которая позволяет получать результаты в разы быстрее традиционных решений. Также я подсвечу, как устроен этот продукт, чем он отличается от реляционных баз данных, и в каких сценариях его использование может дать бизнесу реальное преимущество.
Пара слов о компании Hybrid. Мы — независимая AdTech-экосистема с собственным стеком технологий и решений для любых рекламных целей. Развиваем собственные технологии благодаря in-house отделу разработки, который каждый день работает над их улучшением. ClickHouse — инструмент, который мы выбираем для хранения данных за высокую скорость обработки запросов, эффективное сжатие данных и масштабируемость.
Введение в ClickHouse
Преимущества
Высокая производительность: ClickHouse обрабатывает миллиарды строк данных за считанные секунды, даже для сложных запросов.
Колоночное хранение данных: Чтение только необходимых столбцов снижает объем обработанных данных и повышает скорость запросов.
Партиционирование и индексация: Логическое разделение данных по партициям (например, по дате) ускоряет поиск.
Сжатие данных: Алгоритмы сжатия минимизируют использование дискового пространства, сохраняя производительность.
Масштабируемость: Распределенное хранение позволяет ClickHouse работать на кластерах серверов.
Как работает ClickHouse
Колоночное хранение: Данные хранятся в столбцах, что позволяет извлекать только нужные поля, что может быть удобно при больших количествах монотонных данных
Партиционирование: Данные разделяются на логические блоки (партиции), что ускоряет доступ к информации.
Сценарии использования ClickHouse
Аналитика данных в реальном времени: Подходит для обработки потоков данных в режиме реального времени и построения онлайн-дашбордов.
Хранение логов и событий: Например, логов веб-серверов или пользовательских действий.
Машинное обучение: Поддерживает хранение больших датасетов для обучения моделей.
Интеграция с BI-системами: Работает с инструментами, такими как Grafana или Apache Superset, для визуализации данных.
Как начать работать с ClickHouse
Сначала давайте поговорим как можно поставить Clickhouse, если вы с этим столкнулись в первый раз.
Для установки на Ubuntu необходимо сделать шаги:
Добавить репозитории и ключи репозитория
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
ARCH=$(dpkg --print-architecture)
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg arch=${ARCH}] https://packages.clickhouse.com/deb stable main" | sudo tee /etc/apt/sources.list.d/clickhouse.list
sudo apt-get update
2. Установить Clickhouse
sudo apt-get install clickhouse-server clickhouse-client
sudo systemctl start clickhouse-server
Дизайн таблиц
Теперь когда у нас есть сервер, давайте немного поговорим про таблицы и данные.
Немного поэкспериментируем, чтобы показать, как это работает. Создаем базу данных и переключимся в нее.
CREATE DATABASE webinar;
USE webinar;
Теперь создаем таблицу, которая будет хранить события, происходящие с рекламным баннером:
CREATE TABLE events (
event_date Date,
event_time DateTime,
user_id UInt32,
event_type String,
platform String,
country String
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, user_id, event_time);
Для вставки данных выполним INSERT запрос c данными в формате JSONEachRow:
INSERT INTO events FORMAT JSONEachRow
{
"event_date": "2024-01-01",
"event_time": "2024-01-01 12:00:00",
"user_id": 12345,
"event_type": "click",
"platform": "mobile",
"country": "US"
}
Чтобы прочитать данные о событиях необходимо выполнить запрос следующего вида:
SELECT
event_date,
event_type,
COUNT(*) AS event_count
FROM events
Однако по мере роста количества данных в таблице, запрос будет становиться все сложнее в обработке. Чтобы в фоне выполнять такие предварительные расчеты можно завести материализованное представление:
CREATE MATERIALIZED VIEW summary_view
ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, event_type)
AS
SELECT
event_date,
event_type,
COUNT(*) AS event_count
FROM events
GROUP BY event_date, event_type;
В Hybrid Platform мы практически повсеместно используем материализованные представления для ускорения запросов. Предварительный сбор данных позволяет нам ускорять загрузку статистических данных.
Недавно мы столкнулись с задачей разделения наших материализованных представлений на таблицу и запрос. Для этого было решено сделать апдейт устаревших настроек, которые нельзя было произвести без замены таблиц.
Опираясь на документацию, наш и индустриальный опыт, мы сделали следующее. Разберем на примере статистики кампаний:
Сначала — самые важные и «грубые» фильтры
Почти все запросы мы фильтруем по дате. Все записи у нас содержат дату и это довольно низкокардинальные данные (данные с меньшим количеством уникальных значений), а этот столбец отлично подходил на роль первого в ORDER BY
.
ORDER BY (EventDate, ...)
2. Добавляем чуть более точные фильтры
Дальше шли project_id и source_id — их кардинальность повыше, но они тоже часто встречались в WHERE
. Расположили их по убыванию важности.
Мы посмотрели на запросы из HybridPlatform и на логику интерфейса. У нас довольно часто встречается привязка к TradingDesk и агентству. А следующим большим фильтром является рекламодатель:
ORDER BY (…TradingDeskId, AgencyId, AdvertiserId…)
3. Остались «неохваченные» фильтры — добавляем их
В таблице, которая агрегирует статистику по кампаниям было бы все же неплохо иметь фильтр по этим самым кампаниям, поэтому добавили еще и CampaignId:
ORDER BY (…CampaignId,…)
4. Улучшаем сжатие за счет похожих данных
Если строки всё ещё неуникальны, можно добавить что-то вроде user_id
или EventName
, чтобы похожие данные лежали рядом. Это помогло сжать данные на 20-30% лучше.
ORDER BY (...EventName, …)
5. Временные ряды: timestamp в конец
Наша идея была затащить в материализованные представления информацию о времени. Но нас интересовало округленное значение. Мы уже в одном представлении использовали функцию toStartOfHourDate
, поэтому решили ее принести и в остальные таблицы для удобства работы.
ORDER BY (…StartOfHourDate)
Итоговый ORDER BY
получился следующий:
ORDER BY (EventDate, TradingDeskId, AgencyId, AdvertiserId, CampaignId, EventName, StartOfHourDate)
На что мы смотрели при выборе столбцов для первичного ключа?
В ClickHouse первичный ключ (PRIMARY KEY) и ORDER BY
— это одно и то же. Формально ORDER BY
определяет физический порядок хранения данных, а первичный ключ влияет на индексацию.
В отличие от традиционных реляционных баз данных, ClickHouse использует разреженные индексы. Это означает, что вместо индексации каждой строки, ClickHouse группирует строки в гранулы (обычно по 8192 строки) и создает индексные отметки только для первой строки в каждой грануле. Такой подход значительно ускоряет фильтрацию данных, так как бинарный поиск по индексным отметкам требует всего нескольких шагов.
В большинстве случаев роль первичного ключа в ClickHouse выполняет ORDER BY
. Однако в MergeTree и его вариациях есть особенности.
В MergeTree PRIMARY KEY
можно задать короче, чем ORDER BY
.
Если ORDER BY
состоит из нескольких столбцов, можно задать PRIMARY KEY
, включающий только первые N столбцов. Это уменьшит размер индексов, сохранив эффективность фильтрации.
Чтобы ускорить работу с таблицами выбирайте столбцы с низкой кардинальностью, чтобы ускорить построение индексов. Если первичный ключ не указан, ClickHouse использует для этого ключ сортировки.
Хороший ORDER BY
обычно включает 3-5 столбцов, расположенных в порядке увеличения кардинальности: от наименьшей (и самой важной для фильтрации) слева до наибольшей (менее важной для фильтрации) справа.

ClickHouse идеально подходит для хранения и анализа данных из DSP и SSP, через которые проходит огромный поток информации об аукционах, показах и кликах. Он позволяет эффективно собирать, обрабатывать и анализировать эти данные в режиме реального времени.
В компании Hybrid мы выбрали ClickHouse, потому что он обеспечивает:
Высокую скорость обработки запросов — критично при работе с большими объемами данных.
Эффективное сжатие — позволяет хранить терабайты статистики без избыточных затрат на инфраструктуру.
Масштабируемость легко справляется с растущими нагрузками и увеличением количества данных.
Если вы используете наши продукты Hybrid Platform или VOX, то могли видеть статистику в личных кабинетах — она как раз хранится и обрабатывается в ClickHouse. Это позволяет обеспечивать быстрый доступ к данным и детальную аналитику для наших пользователей.
Заключение
Наша команда активно использует ClickHouse для аналитики, ведь он идеально подходит для работы с большими объемами информации в реальном времени. В конце ноября 2024 года я провел вебинар «Быстрое погружение в ClickHouse». Он и послужил в качестве основы для этого материала. Вот ссылки, по которым вы можете ознакомиться с ним подробнее.
Видео вебинара: Ссылка на видео
Презентация: Ссылка на презентацию
Если после вебинара у вас возник дополнительный интерес к Clickhouse, дайте знать об этом в комментариях. Мы открыты к обсуждению новых тем и готовы делиться опытом: будь то успешные кейсы применения инструмента, его интеграция с различными платформами или другие аспекты, которые могут быть полезны вам.