Скидка до 55% и курс по ИИ в подарок 2 дня 10 :28 :07 Выбрать курс
Код
#статьи

ClickHouse: что это за СУБД, как она устроена и для чего нужна

Изучаем СУБД и замеряем производительность.

Изображение: Ekaterina Goncharova / Getty Images

Представьте, что вы аналитик и вам надо посчитать выручку по всем регионам за год, а в таблице заказов миллиард строк. В PostgreSQL после отправки запроса СУБД задумается, а вы со спокойной совестью сможете пойти заваривать кофе. С ClickHouse таких кофе-брейков не будет — ответ придёт за секунды.

В этой статье мы разберём, чем ClickHouse отличается от обычных баз, как устроено колоночное хранение и почему оно такое быстрое. Вы узнаете, где применяют ClickHouse, какие у неё плюсы и минусы и когда стоит брать ClickHouse, а когда лучше остаться на PostgreSQL или MySQL.

Содержание


Что такое ClickHouse

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

Обычно ClickHouse используют в качестве аналитического хранилища. Система хорошо подходит для запросов, в которых нужно обработать миллионы или даже миллиарды строк: посчитать события за определённый период, сгруппировать пользователей по странам, построить отчёт по продажам, найти аномалии в логах или рассчитать продуктовые метрики.

При этом ClickHouse хуже подходит для задач, где нужны частые точечные изменения отдельных записей, сложные транзакции или постоянное чтение одной строки по ключу. Например, хранить в ней состояние корзины интернет-магазина или данные личного кабинета обычно не стоит. С такой нагрузкой лучше справляются транзакционные СУБД вроде PostgreSQL и MySQL.

Выполненный агрегирующий запрос в ClickHouse
Скриншот: PowerShell Windows 10 / Skillbox Media

Как появилась ClickHouse

ClickHouse появилась внутри «Яндекса». Разработку начали в 2009 году для «Яндекс Метрики»: сервису надо было в реальном времени анализировать постоянно растущий поток данных о действиях пользователей. В 2012 году ClickHouse начали использовать в продакшене, а к 2014 она стала основной технологией новой версии «Метрики».

В июне 2016 года «Яндекс» открыл исходный код ClickHouse под лицензией Apache 2.0. После этого СУБД начали использовать сторонние компании, а вокруг проекта сформировалось международное сообщество разработчиков.

В сентябре 2021 года команда проекта перешла в независимую американскую компанию ClickHouse Inc., зарегистрированную в Делавэре со штаб-квартирой в районе Сан-Франциско. После последнего раунда финансирования в 2025 году компанию оценили примерно в 15 миллиардов долларов.

Несмотря на происхождение проекта, сейчас ClickHouse Inc. — независимая американская компания. При этом сама СУБД остаётся открытой и распространяется под Apache 2.0, поэтому её можно бесплатно развернуть на собственных серверах. В России также доступны управляемые версии ClickHouse у локальных облачных провайдеров — например, Yandex Cloud, Selectel и MWS Cloud Platform.

Отличия от PostgreSQL и MySQL

Главное отличие ClickHouse от PostgreSQL и MySQL — в задачах, под которые спроектированы эти СУБД. PostgreSQL и MySQL в первую очередь рассчитаны на OLTP-нагрузку — множество небольших операций с отдельными записями. Например, провести платёж, создать заказ, изменить его статус или получить данные конкретного пользователя.

ClickHouse ориентирован на OLAP-нагрузку — аналитические запросы, которые обрабатывают большие объёмы данных. Вместо поиска одной записи такой запрос может пройти по миллионам строк, чтобы посчитать сумму продаж за год, сгруппировать пользователей по странам или определить количество событий каждого типа.

Отсюда следует разница в устройстве СУБД. PostgreSQL и MySQL обычно хранят данные по строкам — значения одной записи находятся рядом, поэтому систему удобно использовать, когда нужно быстро прочитать или изменить запись целиком. ClickHouse хранит данные по столбцам. Если для отчёта нужны только дата, страна и сумма покупки из таблицы с десятками полей, СУБД может прочитать именно эти столбцы, а остальные не трогать.

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

Ещё одно важное различие — первичный ключ. В PostgreSQL и MySQL он гарантирует уникальность записи: две строки с одинаковым значением первичного ключа добавить нельзя. В ClickHouse первичный ключ сам по себе уникальности не обеспечивает. Он нужен прежде всего для того, чтобы СУБД могла быстрее определить, какие части данных читать при выполнении запроса, а какие можно пропустить.

Создаём тестовую базу данных

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

Повторить примеры можно на обычном ноутбуке. На Linux и macOS ClickHouse работает нативно, а на Windows понадобится WSL.

Сначала скачиваем ClickHouse и запускаем её в локальном режиме:

curl https://clickhouse.com/ | sh
./clickhouse local --path ~/ch-demo

Теперь создадим базу shop и таблицу events с событиями интернет-магазина. В ней будет шесть столбцов: дата и время события, идентификатор пользователя, тип события, страна и сумма покупки:

CREATE DATABASE IF NOT EXISTS shop;

CREATE TABLE shop.events
(
    event_date Date,
    event_time DateTime,
    user_id UInt32,
    event LowCardinality(String),
    country LowCardinality(String),
    revenue Decimal(10, 2)
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, country, user_id);

Две особенности этой таблицы пригодятся нам дальше. Тип LowCardinality (String) подходит для столбцов с небольшим количеством повторяющихся значений, а ORDER BY определяет порядок данных внутри таблицы.

Осталось наполнить таблицу данными. Сгенерируем их средствами самой ClickHouse: функция numbers() создаст нужное количество строк, а rand() заполнит поля псевдослучайными значениями.

INSERT INTO shop.events
SELECT
    d,
    toDateTime(d) + rand(3) % 86400,
    rand(4) % 500000,
    ['view', 'click', 'add_to_cart', 'purchase'][(rand(5) % 4) + 1],
    ['RU', 'KZ', 'BY', 'AM', 'UZ', 'GE'][(rand(6) % 6) + 1],
    round((rand(7) % 3000000) / 100, 2)
FROM
(
    SELECT toDate('2025-01-01') + (number % 365) AS d
    FROM numbers(20000000)
);

В результате получаем 20 миллионов событий за 2025 год для 500 тысяч пользователей. Именно эту базу мы будем использовать во всех следующих примерах.

Как устроено колоночное хранение

В строковых СУБД значения одной записи хранятся рядом. ClickHouse хранит данные по столбцам. Это значит, что значения event_date находятся вместе, значения country — отдельно, значения revenue — отдельно и так далее.

У такого подхода есть два важных преимущества. Во-первых, запрос читает только те столбцы, которые ему действительно нужны. Если в таблице 100 столбцов, а для расчёта нужны только три, то ClickHouse не нужно загружать остальные 97.

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

Посмотрим, как это работает на нашей тестовой таблице. ClickHouse хранит статистику о размере столбцов в системной таблице system.columns. Нас интересуют два показателя: data_uncompressed_bytes показывает объём данных до сжатия, а data_compressed_bytes — сколько места они занимают после сжатия на диске.

Запустим функцию formatReadableSize(), которая переведёт байты в читаемые мегабайты, и поделим одно значение на другое, чтобы узнать коэффициент сжатия:

SELECT
    name AS column,
    type,
    formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
    formatReadableSize(sum(data_compressed_bytes))   AS compressed,
    round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 1) AS ratio
FROM system.columns
WHERE database = 'shop' AND table = 'events'
GROUP BY name, type
ORDER BY ratio DESC;

Вот какие данные мы получили для нашей таблицы.

КолонкаТипБез сжатияНа дискеВо сколько раз меньше
event_dateDate23,50 МиБ111,06 КиБ216,7
countryLowCardinality(String)11,77 МиБ88,16 КиБ136,7
eventLowCardinality(String)11,77 МиБ6,81 МиБ1,7
revenueDecimal(10, 2)93,99 МиБ57,27 МиБ1,6
event_timeDateTime47,00 МиБ46,73 МиБ1,0
user_idUInt3247,00 МиБ47,18 МиБ1,0
Вся таблица235,03 МиБ158,18 МиБ1,49

Общий коэффициент сжатия можно получить отдельным запросом:

SELECT
    formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
    formatReadableSize(sum(data_compressed_bytes))   AS compressed,
    round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 2) AS ratio
FROM system.columns
WHERE database = 'shop' AND table = 'events';

Разброс между столбцами получился большим. Лучше всего сжались event_date и country. Наша таблица отсортирована сначала по дате, а затем по стране, поэтому одинаковые и близкие значения часто оказываются рядом — это сильно помогает алгоритмам сжатия.

А вот user_id и event_time почти не сжались. Мы заполнили их псевдослучайными значениями, поэтому в данных почти нет повторяющейся структуры, которой мог бы воспользоваться алгоритм.

Из-за этого общий результат нашего синтетического теста довольно скромный — таблица уменьшилась примерно в 1,5 раза. На реальных наборах данных эффект может быть заметно сильнее.

Отдельно стоит учитывать LowCardinality (String). Этот тип сам по себе оптимизирует хранение строк с небольшим количеством уникальных значений. ClickHouse создаёт словарь значений и вместо самих строк хранит ссылки на него. Поэтому показатели data_uncompressed_bytes для таких столбцов нельзя напрямую воспринимать как размер тех же данных в обычном String.

Архитектура: движки, парты и ключ сортировки

В ClickHouse каждая таблица использует определённый движок. Он задаёт, как СУБД хранит данные, обрабатывает вставки, объединяет части таблицы и работает с дубликатами. Для большинства аналитических задач используют движки семейства MergeTree.

Данные в MergeTree хранятся отдельными частями — партами. Когда ClickHouse получает новую порцию данных, он создаёт один или несколько новых партов. Внутри каждого из них строки уже отсортированы по ключу таблицы, разбиты по столбцам, сжаты и записаны на диск.

Со временем таких частей становится много, поэтому ClickHouse в фоне объединяет небольшие парты в более крупные. Этот процесс называется слиянием, или merge, — отсюда и название семейства MergeTree.

Как MergeTree сливает данные
Изображение: Mermaid.ai / Skillbox Media

Из этой архитектуры следует важное правило: данные в ClickHouse лучше записывать крупными пачками. Если постоянно отправлять отдельные строки небольшими INSERT, таблица быстро обрастёт множеством мелких партов. ClickHouse придётся постоянно объединять их в фоне, а на это расходуются процессорное время, память и операции с диском.

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

При создании таблицы важны три параметра:

  • ORDER BY — задаёт порядок сортировки внутри партов. От него сильнее всего зависит и скорость запросов, и степень сжатия. Ставьте в начало ключа те колонки, по которым чаще всего фильтруете.
  • PARTITION BY — делит данные на логические куски, обычно по месяцам. Партиции удобно удалять целиком, и они помогают отсекать данные на старте запроса.
  • PRIMARY KEY — индекс, с помощью которого движок понимает, какие блоки можно пропустить. По умолчанию совпадает с ORDER BY.

В кластере ClickHouse раскидывает данные по нескольким серверам и реплицирует их. За координацию реплик отвечает ClickHouse Keeper.

ClickHouse на практике: считаем метрики интернет-магазина

Таблица shop.events у нас уже есть — на ней мы проверяли сжатие, колоночное чтение и работу ключа сортировки. Теперь посмотрим, как ClickHouse решает более прикладную задачу: посчитаем показатели интернет-магазина и подготовим витрину для дашборда.

Начнём с отчёта по продажам за июнь 2025 года. Для каждой страны посчитаем количество покупок, число покупателей и общую выручку:

SELECT
    country,
    count()            AS purchases,
    uniq(user_id)      AS buyers,
    round(sum(revenue)) AS revenue
FROM shop.events
WHERE event = 'purchase'
  AND event_date >= '2025-06-01'
  AND event_date <  '2025-07-01'
GROUP BY country
ORDER BY revenue DESC;

Функция uniq() приблизительно считает количество уникальных значений. Для аналитических задач такой оценки часто достаточно, а если требуется точный результат, можно использовать uniqExact().

На нашем стенде запрос обработал 1,64 миллиона строк и 26,30 МБ данных, выполнился за 0,068 секунды и использовал 8,47 МиБ памяти. Эти показатели clickhouse-client выводит после выполнения запроса.

Для разового отчёта этого достаточно. Но представим, что те же показатели постоянно запрашивает дашборд. Каждый раз пересчитывать их по миллионам исходных событий необязательно — часть работы можно выполнить заранее.

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

Создадим небольшую витрину с количеством покупок и выручкой по странам за каждый день:

CREATE TABLE shop.daily_country
(
    event_date Date,
    country    LowCardinality(String),
    purchases  UInt64,
    revenue    Decimal(38, 2)
)
ENGINE = SummingMergeTree
ORDER BY (event_date, country);

CREATE MATERIALIZED VIEW shop.mv_daily TO shop.daily_country AS
SELECT
    event_date,
    country,
    count()      AS purchases,
    sum(revenue) AS revenue
FROM shop.events
WHERE event = 'purchase'
GROUP BY event_date, country;

Теперь вместо исходных событий дашборд может обращаться к значительно меньшей таблице. Например, июньский отчёт строится так:

SELECT
    country,
    sum(purchases) AS purchases,
    sum(revenue) AS revenue
FROM shop.daily_country
WHERE event_date >= '2025-06-01'
    AND event_date < '2025-07-01'
GROUP BY country
ORDER BY revenue DESC;

Здесь снова используем sum(), хотя данные уже агрегированы. Дело в том, что SummingMergeTree объединяет строки с одинаковым ключом во время фоновых слияний. До очередного слияния агрегаты за одну дату и страну могут физически находиться в нескольких строках, поэтому при чтении их нужно суммировать.

В результате дашборд работает уже не с миллионами событий, а с компактной таблицей дневных агрегатов. При этом исходные данные остаются в shop.events. По ним можно строить другие отчёты или при необходимости заново рассчитать витрину.

Такой подход переносит часть вычислений с момента чтения на момент записи. Чем чаще выполняется один и тот же тяжёлый аналитический запрос, тем больше пользы может дать заранее подготовленная витрина.

Веб-интерфейс ClickHouse с выполненным запросом по странам и таблицей результата
Скриншот: ClickHouse / Skillbox Media

Где применяют ClickHouse

ClickHouse используют там, где данных много, они в основном дописываются, а не изменяются, и по ним регулярно считают агрегаты. Чаще всего встречаются такие сценарии:

  • Продуктовая и веб-аналитика. ClickHouse используют для обработки больших потоков событий: просмотров страниц, кликов, регистраций, покупок и других действий пользователей. На этих данных считают воронки, удержание, активность, когорты и другие продуктовые метрики.
  • Логи и наблюдаемость. В ClickHouse можно складывать логи приложений, серверов и инфраструктуры, а затем искать ошибки, всплески задержек и аномальное поведение сервисов. Такой сценарий особенно удобен, когда нужно быстро анализировать события сразу по всему стеку за длительный период.
  • Метрики приложений и инфраструктуры. ClickHouse подходит для хранения и анализа временных рядов: загрузки CPU, использования памяти, сетевой активности, времени ответа и других показателей. На их основе считают процентили, отслеживают динамику и сравнивают состояние системы между разными периодами.
  • Финансовая аналитика и антифрод. СУБД используют для анализа больших потоков операций и поиска нетипичного поведения. Например, можно искать резкие отклонения от обычных трат, необычные сочетания параметров транзакций или всплески активности по отдельным сегментам пользователей.
  • Маркетинговая аналитика. ClickHouse помогает объединять данные из рекламных кабинетов, CRM, с сайта и других источников в одном хранилище. После этого можно считать стоимость привлечения, конверсии, атрибуцию и сравнивать эффективность кампаний, каналов и аудиторных сегментов.

Во всех этих сценариях ClickHouse решает одну и ту же задачу — быстро обрабатывать большие объёмы событий и находить в них нужные закономерности. Чем больше данных накапливается и чем чаще по ним нужно строить отчёты, срезы и агрегаты, тем заметнее преимущества такой архитектуры.

Плюсы и минусы ClickHouse

ClickHouse очень хороша в тех задачах, для которых её проектировали: хранить большие объёмы данных и быстро выполнять по ним аналитические запросы. Но специализация накладывает ограничения — использовать эту СУБД как универсальную замену PostgreSQL или MySQL обычно не стоит.

Плюсы ClickHouse:

  • Высокая скорость аналитических запросов. Колоночное хранение, сжатие, векторизованное выполнение и разреженные индексы позволяют быстро агрегировать миллионы и миллиарды строк.
  • Эффективное хранение данных. Значения одного столбца часто хорошо сжимаются, поэтому большие таблицы могут занимать заметно меньше места на диске. Заодно уменьшается объём данных, который приходится читать при выполнении запросов.
  • Работа с большими объёмами. ClickHouse рассчитана на таблицы с миллиардами строк и большие потоки новых событий. При необходимости нагрузку можно распределять между несколькими серверами с помощью шардирования и репликации.
  • Знакомый SQL. Для работы используется SQL, поэтому разработчику, который уже знаком с PostgreSQL, MySQL или другой реляционной СУБД, не приходится изучать совершенно новый язык запросов. При этом у ClickHouse есть собственные функции и особенности диалекта.
  • Открытый исходный код. ClickHouse распространяется под лицензией Apache 2.0. Её можно самостоятельно развернуть на своих серверах или использовать готовый управляемый сервис в облаке.

Минусы ClickHouse:

  • Не подходит на роль классической OLTP-базы. ClickHouse создавалась прежде всего для аналитики, а не для корзин интернет-магазинов, банковских транзакций и других сценариев, где постоянно читают и изменяют отдельные записи.
  • SQL ведёт себя не везде привычно. Хотя ClickHouse поддерживает SQL, некоторые конструкции и принципы работы отличаются от PostgreSQL и MySQL. Особенно это касается транзакций, обновлений, индексов, ограничений целостности и движков таблиц.
  • Кластеры усложняют эксплуатацию. Один сервер ClickHouse поднять сравнительно просто, но крупная распределённая система с шардами, репликами и ClickHouse Keeper требует отдельных знаний в мониторинге, настройке и восстановлении после сбоев.
  • Для небольших проектов может быть избыточным. Если данных немного, а аналитические запросы выполняются редко, отдельная ClickHouse добавит ещё одну систему, которую придётся разворачивать, обновлять и поддерживать. В таких случаях возможностей PostgreSQL или другой уже используемой СУБД может быть достаточно.

В итоге ClickHouse стоит выбирать, когда профиль задачи совпадает с архитектурой СУБД. Если данные поступают большими потоками, редко изменяются после записи и по ним постоянно считают агрегаты, то ClickHouse может стать хорошим решением.

Мы составили блок-схему, с которой проще решить, стоит ли использовать в проекте ClickHouse. Просто отвечайте на вопросы и смотрите, куда вас приведут ответы.

Изображение: Mermaid.ai / Skillbox Media

ClickHouse против конкурентов

У ClickHouse нет одного прямого конкурента. В разных сценариях она пересекается с транзакционными СУБД, классическими хранилищами данных, облачными аналитическими платформами и поисковыми движками. Поэтому сравнивать их лучше по конкретным задачам.

СистемаВ чём сильнее ClickHouseВ чём сильнее конкурент
PostgreSQLМассовые агрегации по большим таблицам, работа с потоками событий, сжатиеТранзакции, точечные операции, ограничения целостности, развитая экосистема расширений
MySQLАналитические запросы, обработка событий и логовCRUD-приложения, частые изменения отдельных записей, привычная модель для веб-разработки
GreenplumБыстрые запросы по большим денормализованным таблицам, относительно простое развёртывание одного узлаКлассические DWH-схемы, сложная реляционная аналитика и большое количество JOIN
DuckDBСерверная работа под постоянной нагрузкой, репликация, кластеры и непрерывная загрузка данныхЛокальный анализ файлов без отдельного сервера, встраивание в приложения и скрипты
Snowflake, BigQueryВозможность работать на собственном железе, полный контроль над инфраструктурой и расходамиПолностью управляемая инфраструктура и автоматическое масштабирование вычислительных ресурсов
ElasticsearchАгрегации по большим объёмам логов, эффективное хранение и сжатиеПолнотекстовый поиск, анализ текста, релевантность и ранжирование результатов

Оценить скорость работы ClickHouse можно в официальном бенчмарке ClickBench. Для анализа нём используют одну таблицу примерно на 100 миллионов строк, полученных из реальных данных веб-аналитики, и набор из 43 запросов. Они проверяют полное и отфильтрованное сканирование данных, агрегации, работу со строками, индексами и другие типичные аналитические операции.

Результаты бенчмарка ClickBench
Скриншот: Benchmark / Skillbox Media

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!

Освойте инструменты аналитика на практике
На бесплатном курсе Skillbox вы за 4 дня попробуете разные направления в Data Science и решите 4 реальные задачи.
Подробнее
Уже работаете с данными?
Систематизируйте знания в Data Science и попробуйте инструменты, которые помогут упростить ежедневную работу.
Узнать как
Попробуйте data science на бесплатном курсе
Пройдите курс по data science и изучите 3 направления в работе с данными. Решите, в какой сфере хотите развиваться дальше, и получите ценные подарки.
Пройти курс →
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована