Databases

ClickHouse

ClickHouse — открытая колоночная СУБД для аналитики, способная агрегировать миллиарды строк за секунды на обычном железе.

Что такое ClickHouse

ClickHouse (кликхаус) — открытая колоночная СУБД, рассчитанная на аналитические запросы по очень большим объёмам данных. Изначально разработана в Яндексе для Яндекс.Метрики, опубликована под лицензией Apache 2.0 и с 2021 года развивается отдельной компанией ClickHouse Inc.

Задача, под которую она сделана, — OLAP: агрегировать миллиарды строк логов, событий и метрик за секунды. На типовой задаче «посчитать статистику за месяц по 10 млрд событий» ClickHouse отвечает там, где PostgreSQL уйдёт в многочасовой скан.

Почему колоночное хранение быстрее

Строковые СУБД кладут строку целиком в одно место на диске. Колоночные хранят каждую колонку отдельным файлом.

SELECT country, count() FROM events WHERE date >= '2026-06-01' GROUP BY country;

В таблице 50 колонок, запросу нужны две. Строковая база всё равно поднимет с диска все 50 — они лежат вперемешку. ClickHouse прочитает ровно country и date, то есть в 25 раз меньше данных. Плюс однотипные значения в колонке сжимаются в разы лучше вперемешку лежащих, а обработка идёт векторно — блоками по многу значений за инструкцию.

Обратная сторона того же дизайна: точечные операции здесь дороги. Достать одну строку по ключу — значит собрать её из десятков файлов, поэтому для OLTP ClickHouse не годится.

Что ClickHouse не умеет

Это не замена реляционной базе, и попытка использовать его как основную БД приложения заканчивается плохо:

  • Нет полноценных транзакций. ACID в привычном виде отсутствует.
  • UPDATE и DELETE — тяжёлые операции. Реализованы как асинхронные мутации, переписывающие целые куски данных. Не для точечных правок.
  • Уникальность не гарантируется. PRIMARY KEY здесь не про уникальность, а про порядок сортировки данных на диске; ограничения UNIQUE нет.
  • Слабое место — JOIN. Соединения работают, но требуют внимания к порядку таблиц и памяти; модель данных обычно денормализуют.

Стандартная связка: PostgreSQL как источник истины, ClickHouse — витрина для аналитики, между ними ETL или очередь вроде Kafka.

MergeTree

Основное семейство движков таблиц. Данные пишутся пачками в неизменяемые куски, которые фоновый процесс сливает в более крупные — отсюда название.

CREATE TABLE events (
    ts         DateTime,
    date       Date DEFAULT toDate(ts),
    user_id    UInt64,
    country    LowCardinality(String),
    event_type LowCardinality(String),
    revenue    Decimal(10,2)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(date)      -- партиции по месяцам
ORDER BY (country, date, user_id)  -- порядок на диске = первичный ключ
TTL date + INTERVAL 6 MONTH;     -- автоудаление старых данных

Три решения определяют скорость запросов:

  • ORDER BY — колонки, по которым чаще всего фильтруете, слева. Разреженный индекс строится именно по нему.
  • PARTITION BY — обычно месяц. Партиции целиком отбрасываются при фильтре по дате и мгновенно удаляются через DROP PARTITION. Слишком мелкие партиции (по часам) плодят куски и вредят.
  • LowCardinality(String) — словарное сжатие для колонок с малым числом различных значений (страна, тип события, статус). Дёшево и заметно ускоряет.

Полезные варианты движка: ReplacingMergeTree (дедупликация по ключу при слиянии), SummingMergeTree и AggregatingMergeTree (преагрегация), ReplicatedMergeTree (репликация через ZooKeeper/ClickHouse Keeper).

Вставка данных

-- Плохо: 1000 запросов по одной строке
INSERT INTO events VALUES (now(), 42, 'RU', 'click', 0);

-- Хорошо: одна пачка на десятки тысяч строк
INSERT INTO events FORMAT CSV

ClickHouse любит крупные редкие вставки и плохо переносит поток одиночных INSERT — каждый порождает отдельный кусок на диске, и фоновые слияния не успевают. Практика: буферизовать на стороне приложения, писать пачками раз в несколько секунд, либо ставить перед базой Kafka.

Работа с сервером

docker run -d --name ch -p 8123:8123 -p 9000:9000 clickhouse/clickhouse-server
clickhouse-client --host 127.0.0.1
-- Сколько занимают таблицы и как сжались
SELECT table,
       formatReadableSize(sum(bytes_on_disk)) AS disk,
       round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 1) AS ratio
FROM system.parts WHERE active GROUP BY table;

Порт 8123 — HTTP-интерфейс, 9000 — нативный протокол. Системные таблицы system.parts, system.query_log, system.merges — основной инструмент диагностики.

Железо

ClickHouse упирается в диск и память. Практические ориентиры: NVMe SSD вместо HDD (сканы читают большие объёмы), побольше ядер CPU — запрос распараллеливается по ним, RAM под GROUP BY с большим числом ключей и JOIN. Данные сжимаются обычно в несколько раз, поэтому места нужно меньше, чем кажется по сырому объёму логов.

Связанные термины

  • OLAP — класс задач, под которые сделан ClickHouse
  • СУБД — класс систем, к которому он относится
  • PostgreSQL — строковая СУБД, дополняющая ClickHouse
  • Greenplum — другой подход к аналитике на MPP
  • DWH / хранилища данных — архитектура, где живёт ClickHouse
  • Apache Kafka — типичный источник потока событий

Готовы запустить GPU-задачу?

Запустить GPU-сервер