Загрузка в ClickHouse связывает три решения: как сгруппировать строки для вставки, как представить значения и как обработать повтор после ошибки. Успешный INSERT должен означать именно ту гарантию, на которую рассчитывает отправитель.
Синхронная вставка и размер порции
Обычная синхронная вставка в локальный MergeTree обрабатывает входной блок и записывает части. Если данные относятся к нескольким партициям, частей может быть несколько. Много маленьких INSERT увеличивает число parts, метаданных и работу фоновых merges.
Несколько строк передают одной командой, например для таблицы events с полями event_id и event_type:
INSERT INTO events (event_id, event_type) VALUES
(1, 'click'), (2, 'view'), (3, 'click');Три строки здесь только показывают синтаксис. Рабочую порцию выбирают по числу строк, байтам, доступной памяти и допустимой задержке. Один очень большой пакет может долго занимать память и усложнять повтор; слишком маленькие пакеты создают лишние части. Важна и численность одновременно загружаемых партиций.
Явный список колонок защищает загрузку от перестановки полей схемы. Типы, часовой пояс, обязательные поля и правила обработки неверных значений входят в договор с источником.
Формат данных
| Формат | Как представлены значения | Что учитывать |
|---|---|---|
| CSVWithNames | Строки с заголовком колонок | Кавычки, разделитель, кодировку и настройки сопоставления полей |
| JSONEachRow | Один JSON-объект на строку | Имена полей, типы и поведение отсутствующих значений |
| Parquet | Типизированные колонки в файле | Совместимость схемы и преобразование типов |
| Native | Внутренние бинарные блоки ClickHouse | Удобен клиентам, понимающим протокол и типы ClickHouse |
Формат описывает представление входа, а не движок целевой таблицы. JSONEachRow не требует колонки типа JSON. Файл Parquet после загрузки в MergeTree не становится частью таблицы в своём исходном формате.
Источник может передавать данные через native client, HTTP API, библиотеку, INSERT SELECT или интеграционный инструмент. Файлы, которые видит сервер, и файлы на машине клиента — разные пространства. Это важно при выборе способа чтения.
Асинхронные вставки
Async inserts позволяют серверу накопить несколько маленьких запросов в буфере и записать их вместе. Буферы разделяются по форме запроса и настройкам; это не единый общий пакет всех клиентов.
При async_insert = 1 и wait_for_async_insert = 1 клиент ждёт flush и получает ошибку, если накопленная вставка не выполнена. При wait_for_async_insert = 0 подтверждение относится к приёму в буфер: после него возможна ошибка записи, которую клиент уже не увидит как ответ своей команды. Такой режим требует отдельно продуманной сохранности.
Async inserts уменьшают давление маленьких частей, но не проверяют бизнес-уникальность событий. Они также не отменяют требований к памяти, задержке и наблюдению за ошибками.
Повторы и граница подтверждения
После сетевого таймаута отправитель может не знать, выполнена ли вставка. Повтор обеспечивает доставку, но способен повторно добавить данные. PRIMARY KEY MergeTree этому не препятствует.
Insert deduplication имеет ограниченное окно и правила распознавания блока или токена. При перепаковывании тех же событий в другие блоки результат зависит от выбранного механизма. Дедупликация блоков не равна бессрочной уникальности event_id.
Гарантии повторов для async inserts и связанных materialized views менялись между версиями. Современные гарантии нельзя автоматически переносить на учебную 25.8. Для нужной версии проверяют сохранность исходной таблицы и повторный вклад в target view вместе. В распределённой загрузке дополнительно выясняют, означает ответ запись на шард или только помещение в очередь Distributed.