Основы ClickHouse
ClickHouse - колоночная СУБД, которая не имеет накладных расходов на работу с широкими таблицами с большим количеством столбцов, а значит, позволяет хранить данные в денормализованном виде.
Где применяют ClickHouse
ClickHouse эффективно работает в проектах любого масштаба: от MVP до аналитических систем крупных корпораций. Применяется в:
- Финансовых технологиях
- Научных исследованиях
- Аналитических сервисах (маркетинг, маркетплейсы)
- Работе складов и производств (анализ операций, метрики объектов)
ClickHouse подходит для
- Быстрых запросов по неагрегированной статистике
- Хранения и чтения логов
- SIEM - управления информационной безопасностью и событиями безопасности
- Хранения и обработки денормализованных данных
- Хранения телеметрии, метрик по клиентам и устройствам
- Хранения статистики (например, источник данных в Grafana)
Когда ClickHouse не нужна
- Сложные запросы с использованием JOIN между большими таблицами (требуют много памяти и передачи данных)
- Выборки отдельных строк с низкой задержкой
- OLTP-нагрузка с частыми изменениями и обновлениями данных в реальном времени
ClickHouse рассчитана на увеличение памяти для кеширования часто используемых данных. Для аналитических запросов с большими объёмами данных время ответа меньше, чем у других СУБД.
Ключевые особенности ClickHouse
- Колоночное хранение: данные каждой колонки хранятся в отдельном файле, при чтении распаковываются только нужные колонки, что ускоряет работу.
- Векторный движок: обработка данных по векторам (кусочкам столбцов) с использованием SIMD-инструкций и эффективным кешированием CPU.
- Естественная параллелизация: большие запросы автоматически распараллеливаются на все доступные ресурсы сервера.
- Работа в однонодовой и кластерной конфигурации: позволяет масштабировать обработку данных.
- Масштабируемость: добавление новых узлов для обработки петабайтов данных.
- Децентрализация и отказоустойчивость: асинхронная multi-master репликация с автоматическим восстановлением данных.
- OLAP-ориентированность: аналитическая обработка данных в реальном времени, без поддержки транзакционности OLTP.
Что такое SIMD-инструкции и зачем они нужны в ClickHouse
SIMD (Single Instruction, Multiple Data) - это технология, при которой процессор может выполнять одну и ту же операцию сразу над несколькими данными одновременно.
Как это работает
- Обычно процессор обрабатывает данные по одному элементу за раз (например, складывает два числа).
- С SIMD процессор может, например, сложить сразу 4 или 8 пар чисел за одну команду.
- Это достигается за счёт специальных инструкций и расширенных регистров процессора.
В ClickHouse использование SIMD-инструкций особенно важно из-за её колоночной структуры хранения данных. Поскольку данные хранятся по столбцам, а аналитические запросы часто требуют выполнения одной и той же операции над большим количеством значений в одном столбце (например, фильтрация, агрегация), SIMD-инструкции позволяют значительно ускорить эти вычисления. Вместо того чтобы процессор обрабатывал каждое значение отдельно, SIMD позволяет ему выполнять одну операцию сразу над несколькими значениями одновременно. Например, если нужно сложить два столбца, каждый из которых содержит 1000 чисел, без SIMD процессор выполнит 1000 операций сложения. С использованием SIMD, когда процессор может сложить, скажем, 8 пар чисел одновременно, общее количество операций сократится до 125, что значительно повышает скорость обработки данных.
Режимы работы ClickHouse
Один узел (Single-node)
- Простая установка и запуск сервиса.
- Подходит, если:
- Не требуется отказоустойчивость
- Не нужно горизонтальное масштабирование
- Объём данных умещается на одном сервере
- Ресурсов CPU и RAM достаточно для нагрузки
Кластер
- Требуется ZooKeeper™ (3 или 5 узлов) или ClickHouse Keeper для координации.
- ZooKeeper - сервис-координатор на Java от Apache.
- ClickHouse Keeper - альтернатива ZooKeeper, совместимая с ним.
- Хранит конфигурацию кластера, метаданные, очереди задач, информацию о реплицируемых таблицах.
- Позволяет настраивать репликацию и шардирование для масштабирования и повышения отказоустойчивости.
- Поддержка MPP (выполнение одного запроса на нескольких узлах одновременно).
- Репликация и шардирование могут использоваться вместе или по отдельности.
Отличия ClickHouse от других СУБД
- Оптимизирована под OLAP-задачи, а не OLTP.
- Колоночное хранение и векторная обработка данных.
- Нет поддержки транзакций в режиме реального времени.
- Высокая производительность при аналитических запросах по большим объёмам данных.
Интерфейсы подключения
ClickHouse поддерживает два протокола:
Native TCP:
- Используется в клиенте командной строки и для взаимодействия между серверами
- Имеет меньше накладных расходов
- Реализован на C++, Go, Python
HTTP:
- Более универсальный, реализован практически во всех языках
- Более ограничен по сравнению с нативным интерфейсом
- Имеет больше накладных расходов и меньшую производительность
Оба интерфейса поддерживают шифрование TLS.
Инструменты для подключения
Официально поддерживаемые:
- Консольный клиент
- JDBC-драйвер
- ODBC-драйвер
- Клиентская библиотека C++
Для большинства языков программирования существуют библиотеки, реализующие как Native, так и HTTP-подключения.
Работа с ClickHouse через DBeaver
DBeaver - это универсальный инструмент с графическим интерфейсом для работы с различными СУБД, включая ClickHouse. Для подключения к ClickHouse через DBeaver:
Установка DBeaver:
- Скачайте и установите DBeaver с официального сайта (dbeaver.io)
- Доступны версии для Windows, macOS и Linux
Создание подключения:
- Нажмите "Новое соединение" в меню или на панели инструментов
- Выберите "ClickHouse" из списка доступных баз данных
- Введите параметры подключения:
- Хост (адрес сервера ClickHouse)
- Порт (по умолчанию 8123 для HTTP или 9000 для TCP)
- База данных (имя базы данных)
- Имя пользователя и пароль
- При необходимости настройте SSL/TLS для безопасного подключения
Создание таблиц в ClickHouse
Как и в большинстве баз данных, ClickHouse логически группирует таблицы в базы данных. Используйте команду CREATE DATABASE
, чтобы создать новую базу данных в ClickHouse:
CREATE DATABASE IF NOT EXISTS helloworld
Аналогично, используйте CREATE TABLE
, чтобы определить новую таблицу. (Если вы не укажете имя базы данных, таблица будет в default
базе данных.) Следующая таблица называется my_first_table
в базе данных helloworld
:
CREATE TABLE helloworld.my_first_table
(
user_id UInt32,
message String,
timestamp DateTime,
metric Float32
)
ENGINE = MergeTree()
PRIMARY KEY (user_id, timestamp)
В приведенном выше примере my_first_table
является таблицей MergeTree
с четырьмя колонками:
user_id
: 32-битное беззнаковое целоеmessage
: строковый тип данныхString
timestamp
: значениеDateTime
, которое представляет момент времениmetric
: 32-битное число с плавающей запятой
Краткое введение в первичные ключи
Прежде чем продолжить, важно понять, как работают первичные ключи в ClickHouse (реализация первичных ключей может показаться неожиданной!):
Внимание
Первичные ключи в ClickHouse не уникальны для каждой строки в таблице
Первичный ключ таблицы ClickHouse определяет, как данные сортируются при записи на диск. Каждые 8,192 строки или 10 МБ данных (называемых гранулярностью индекса
) создают запись в файле индекса первичного ключа. Эта концепция гранулярности создает разреженный индекс, который легко помещается в память, и гранулы представляют собой полоску наименьшего объема данных колонки, которая обрабатывается во время SELECT
запросов.
Первичный ключ можно определить с помощью параметра PRIMARY KEY
. Если вы определите таблицу без указанного PRIMARY KEY
, то ключ становится кортежем, указанным в предложении ORDER BY
. Если вы укажете как PRIMARY KEY
, так и ORDER BY
, первичный ключ должен быть префиксом порядка сортировки.
Первичный ключ также является ключом сортировки, который представляет собой кортеж (user_id, timestamp)
. Таким образом, данные, хранящиеся в каждом файле колонки, будут отсортированы по user_id
, затем по timestamp
.
Вставка данных в ClickHouse
Вы можете использовать знакомую команду INSERT INTO TABLE
с ClickHouse. Давайте вставим некоторые данные в созданную таблицу.
INSERT INTO helloworld.my_first_table (user_id, message, timestamp, metric) VALUES
(101, 'Hello, ClickHouse!', now(), -1.0 ),
(102, 'Insert a lot of rows per batch', yesterday(), 1.41421 ),
(102, 'Sort your data based on your commonly-used queries', today(), 2.718 ),
(101, 'Granules are the smallest chunks of data read', now() + 5, 3.14159 )
Чтобы убедиться, что все сработало, мы выполним следующий запрос SELECT
:
SELECT * FROM helloworld.my_first_table
ClickHouse - это OLAP (Online Analytical Processing) система, специально разработанная для аналитики и обработки больших объёмов данных с высокой скоростью и масштабируемостью. Благодаря своей архитектуре, ClickHouse способен обрабатывать миллионы вставок строк в секунду. Такой высокий уровень производительности достигается за счёт параллельной обработки данных и эффективного колоночного сжатия. Однако, в отличие от классических транзакционных СУБД, ClickHouse не гарантирует немедленную согласованность данных: система ориентирована на eventual consistency (согласованность со временем) и оптимизирована для операций, связанных преимущественно с добавлением новых данных.
В противоположность этому, OLTP (Online Transaction Processing) базы данных, такие как PostgreSQL, созданы для работы с транзакциями и обеспечивают строгие гарантии ACID. PostgreSQL, например, реализует механизм MVCC (Multi-Version Concurrency Control), который позволяет обрабатывать параллельные транзакции и поддерживать несколько версий данных одновременно. Такие СУБД отлично подходят для сценариев, где важна мгновенная согласованность данных и поддержка сложных операций изменения, но из-за этого вставка данных может быть медленнее, особенно при больших объёмах.
Чтобы добиться максимальной производительности при вставке данных в ClickHouse, важно учитывать его особенности и придерживаться определённых рекомендаций. Следование этим правилам позволяет избежать типичных ошибок, которые могут возникнуть при попытке использовать ClickHouse так же, как транзакционные OLTP базы данных, и выстроить процесс вставки, оптимальный именно для аналитических нагрузок.
Лучшие практики для вставки данных в ClickHouse
Вставляйте крупными партиями
КаждыйINSERT
создаёт отдельную часть данных, поэтому лучше отправлять меньшее количество крупных партий (от 1 000 до 100 000 строк за раз), чем множество маленьких. Это снижает нагрузку на файловую систему и повышает производительность.Используйте асинхронные вставки для малых партий
Если невозможно собирать большие партии на стороне клиента (например, в системах мониторинга), используйте асинхронные вставки ClickHouse. В этом режиме данные сначала помещаются в буфер, а затем сбрасываются в хранилище одной частью, что позволяет эффективно агрегировать небольшие вставки на сервере.Обеспечивайте идемпотентность повторных вставок
Вставки в ClickHouse по умолчанию идемпотентны: повторная отправка одинаковых данных не приводит к дублированию, если порядок и содержимое совпадают. Это важно для надёжности при сетевых сбоях.Вставляйте напрямую в MergeTree или реплицированные таблицы
Лучше всего вставлять данные сразу в MergeTree-таблицы (или их реплицированные варианты), распределяя нагрузку по шардированным узлам. Для распределённых таблиц рекомендуется включатьinternal_replication=true
.Используйте нативный формат для максимальной производительности
Для самых быстрых вставок используйте нативный формат данных ClickHouse, который минимизирует накладные расходы на парсинг и преобразование. Альтернатива -RowBinary
(оптимально для строкового формата), аJSONEachRow
- для быстрой интеграции, но с большими затратами на парсинг.Применяйте официальный клиент ClickHouse
Официальные клиенты для популярных языков поддерживают оптимальные режимы вставки, включая асинхронные вставки.Воспользуйтесь HTTP-интерфейсом при необходимости
ClickHouse поддерживает HTTP-интерфейс для вставки и чтения данных, что удобно для балансировки нагрузки и интеграции с внешними системами. Однако родной протокол обычно немного быстрее.Знайте ограничения асинхронных вставок
Данные, находящиеся в буфере, недоступны для запросов до сброса в основное хранилище. Параметры сброса буфера можно настраивать.
Выборка данных
ClickHouse поддерживает схожие SELECT запросы, с которыми вы уже знакомы. Например:
SELECT *
FROM helloworld.my_first_table
ORDER BY timestamp
Обновление данных
Используйте команду ALTER TABLE...UPDATE
для обновления строк в таблице:
ALTER TABLE [<database>.]<table> UPDATE <column> = <expression> WHERE <filter_expr>
<expression>
— новое значение для колонки, для которой выполняется <filter_expr>
. <expression>
должен иметь тот же тип данных, что и колонка, или быть конвертируемым в тот же тип данных с помощью оператора CAST
. <filter_expr>
должен возвращать значение UInt8
(ноль или не ноль) для каждой строки данных. Несколько операторов UPDATE
<column>
могут быть объединены в одной команде ALTER TABLE
, разделенные запятыми.
Пример:
ALTER TABLE helloworld.my_first_table
UPDATE message = 'Updated message', metric = metric * 2
WHERE user_id = 102
Удаление данных
Используйте команду ALTER TABLE
для удаления строк:
ALTER TABLE [<database>.]<table> DELETE WHERE <filter_expr>
<filter_expr>
должен возвращать значение UInt8 для каждой строки данных.
Пример:
ALTER TABLE helloworld.my_first_table
DELETE WHERE user_id = 101
Легкие удаления
Другим вариантом для удаления строк является использование команды DELETE FROM
, которая называется легким удалением. Удаленные строки немедленно помечаются как удаленные и автоматически фильтруются из всех последующих запросов, поэтому вам не нужно ждать слияния частей или использовать ключевое слово FINAL
. Очистка данных происходит асинхронно в фоновом режиме.
DELETE FROM [db.]table [ON CLUSTER cluster] [WHERE expr]
Пример:
DELETE FROM helloworld.my_first_table
WHERE user_id = 102