Вставка больших объёмов: батчи, а не строки
Главное правило загрузки: одна большая вставка лучше тысячи маленьких.
Батч (batch) — это одна вставка сразу многих строк (тысячи и более) одним INSERT, вместо множества вставок по одной строке.
Почему мелкие вставки — беда
Вспомним из раздела о MergeTree: каждый INSERT создаёт отдельный кусок (part) на диске. Вставили строку — получили крошечный part. Вставили миллион строк по одной — получили миллион крошечных кусков. Фоновое слияние не успевает их укрупнять, метаданных становится слишком много, и сервер отвечает ошибкой:
DB::Exception: Too many parts (300). Merges are processing significantly slower than inserts.Это самая частая ошибка новичка в ClickHouse.
Как правильно: батчи
Собирайте данные в пачки и вставляйте большими блоками — тысячи или десятки тысяч строк за раз:
INSERT INTO events (event_date, user_id, value) VALUES
('2024-01-01', 1, 10.0),
('2024-01-01', 2, 12.5),
('2024-01-01', 3, 9.0),
-- ... ещё тысячи строк в одном INSERT ...
('2024-01-01', 9999, 7.7);Один такой INSERT создаст один аккуратный part вместо тысяч крошечных.
Загрузка из файлов
Чаще всего данные грузят не руками, а из файлов через clickhouse-client с указанием формата:
# Залить CSV-файл одним батчем
clickhouse-client \
--query="INSERT INTO events FORMAT CSV" \
< data.csv
# Или через HTTP
cat data.csv | curl 'http://localhost:8123/?query=INSERT%20INTO%20events%20FORMAT%20CSV' \
--data-binary @-Сколько строк в батче
Ориентир — от нескольких тысяч до сотен тысяч строк на вставку, и не чаще одного-двух INSERT в секунду на таблицу. Если данные идут потоком (по событию), их нужно буферизовать: накапливать в приложении или использовать таблицу-буфер / интеграционные движки (Kafka), которые сами собирают батчи.
Иллюстрация: число кусков
Сравним «по строке» и «батчами» для миллиона строк (чистый Python):
rows = 1_000_000
batch_size = 50_000
parts_one_by_one = rows # каждая строка -> свой part
parts_batched = rows // batch_size
print("По одной строке -> кусков:", parts_one_by_one)
print("Батчами по 50000 -> кусков:", parts_batched)Вывод:
По одной строке -> кусков: 1000000 Батчами по 50000 -> кусков: 20
Как работает под капотом
Слияние кусков — фоновый процесс с ограниченной пропускной способностью. Когда вставки порождают куски быстрее, чем слияние их укрупняет, число кусков растёт, и срабатывает защита «too many parts». Батчи держат число кусков низким, и слияние спокойно справляется.
Частые ошибки
- INSERT в цикле по строке. Классический способ положить таблицу ошибкой «too many parts».
- Слишком частые вставки. Даже батчи, идущие сто раз в секунду, создают много кусков — буферизуйте.
- Огромный единичный батч в память. Миллиарды строк одним INSERT могут не влезть; грузите крупными, но разумными блоками.
Итоги
- Каждый INSERT — отдельный кусок; мелкие вставки порождают слишком много кусков.
- Вставляйте батчами по тысячи/десятки тысяч строк, нечасто.
- Поток данных буферизуйте (приложение, Buffer-таблица, Kafka).
- «Too many parts» — сигнал, что вставки слишком мелкие/частые.