Отправлять много небольших батчей в синхронном режиме не рекомендуется, так как это приводит к созданию множества частей. Это ухудшает производительность запросов и вызывает ошибки “too many part”.
async_insert.
Асинхронные вставки поддерживаются как через HTTP, так и через native TCP interface.
Когда они включены (async_insert = 1), вставки буферизуются и записываются на диск только после выполнения одного из условий сброса:
- Буфер достигает заданного размера данных (
async_insert_max_data_size, по умолчанию 100 MiB). - Проходит заданный интервал времени (
async_insert_busy_timeout_ms, по умолчанию 200 мс или 1000 мс в Cloud). - Накапливается максимальное количество запросов на вставку (
async_insert_max_query_number, по умолчанию 450).
Выбор режима возврата
wait_for_async_insert.
Если установлено значение 1 (по умолчанию), ClickHouse подтверждает вставку только после того, как данные успешно сбрасываются на диск. Это обеспечивает строгие гарантии сохранности данных и упрощает обработку ошибок: если во время сброса что-то пойдет не так, ошибка будет возвращена клиенту. Этот режим рекомендуется для большинства production-сценариев, особенно если отказы вставки нужно надежно отслеживать.
Бенчмарки показывают, что этот режим хорошо масштабируется при параллелизме — как с 200, так и с 500 клиентами — благодаря адаптивным вставкам и стабильному созданию частей.
Параметр wait_for_async_insert = 0 включает режим “fire-and-forget”. В этом случае сервер подтверждает вставку сразу после буферизации данных, не дожидаясь их записи в хранилище.
Это обеспечивает сверхнизкую latency вставок и максимальный throughput, что идеально подходит для высокоскоростных, но некритичных данных. Однако здесь есть компромиссы: нет гарантии, что данные будут сохранены, ошибки проявляются только во время сброса, а dead-letter queue для неудачных вставок отсутствует — для трассировки сбоев приходится постфактум проверять серверные журналы и системные таблицы. Используйте этот режим только в том случае, если ваша рабочая нагрузка допускает потерю данных.
Бенчмарки также показывают существенное сокращение количества частей и снижение загрузки CPU, когда буфер сбрасывается нечасто (например, каждые 30 секунд), однако риск незаметного сбоя сохраняется.
Мы настоятельно рекомендуем использовать async_insert=1,wait_for_async_insert=1, если вы используете асинхронные вставки. Использование wait_for_async_insert=0 очень рискованно, потому что ваш INSERT-клиент может не узнать о наличии ошибок, а также это может привести к перегрузке, если клиент продолжит быстро записывать данные в ситуации, когда серверу ClickHouse нужно замедлить запись и создать обратное давление, чтобы обеспечить надежность сервиса.
Адаптивные асинхронные вставки
async_insert_use_adaptive_busy_timeout). Вместо фиксированного интервала сброса тайм-аут динамически подстраивается между минимальным значением (async_insert_busy_timeout_min_ms, по умолчанию 50 мс) и максимальным (async_insert_busy_timeout_max_ms, по умолчанию 200 мс или 1000 мс в Cloud) в зависимости от скорости поступления данных.
Когда данные поступают часто, тайм-аут остается ближе к минимальному значению, чтобы сброс происходил раньше и уменьшалась сквозная задержка. Когда данные поступают редко, он увеличивается в сторону максимального значения, чтобы накапливать более крупные батчи. Это особенно полезно в режиме по умолчанию (wait_for_async_insert=1), где фиксированный большой тайм-аут заставлял бы клиентов ждать весь интервал, даже если данные уже готовы к сбросу.
Обработка ошибок
wait_for_async_insert=1) ошибка возвращается клиенту. В режиме fire-and-forget ошибки записываются в серверный журнал и в таблицу system.asynchronous_inserts.
Каждый сброс создает как минимум одну часть для каждого отдельного значения ключа партиционирования в буфере. Даже для таблиц без ключа партиционирования один сброс может создать несколько частей, если объем буферизованных данных превышает max_insert_block_size (по умолчанию ~1 миллион строк).
Несмотря на использование асинхронных вставок, вы все равно можете столкнуться с ошибками “too many parts”, если ключ партиционирования имеет высокую мощность.
Дедупликация и надежность
Включение асинхронных вставок
-
Включение асинхронных вставок на уровне пользователя. В этом примере используется пользователь
default; если вы создадите другого пользователя, подставьте его имя: -
Вы можете указать настройки асинхронной вставки с помощью секции SETTINGS в запросах вставки:
-
Вы также можете указать настройки асинхронной вставки как параметры подключения при использовании клиентской библиотеки ClickHouse для языка программирования.
Например, вот как это можно сделать в строке подключения JDBC, если вы используете драйвер ClickHouse Java JDBC для подключения к ClickHouse Cloud:
Асинхронные вставки не применяются к запросам
INSERT INTO ... SELECT. Если вставка содержит секцию SELECT, запрос всегда выполняется синхронно, независимо от настройки async_insert.Сброс буферов при завершении работы
Сравнение с буферными таблицами
- Изменения DDL не требуются. Асинхронные вставки прозрачны — достаточно включить настройку, а не создавать дополнительные таблицы.
- Буферизация по форме запроса. Асинхронные вставки поддерживают отдельные буферы для каждой уникальной формы запроса и комбинации настроек, что позволяет применять более гибкие политики сброса. Буферные таблицы используют один буфер на целевую таблицу.
- Надёжность. В режиме по умолчанию (
wait_for_async_insert=1) данные записываются на диск до того, как клиент получит подтверждение. Буферные таблицы работают по принципу fire-and-forget — при сбое буферизованные данные теряются. - Поведение в кластере. В кластерах буферы асинхронных вставок поддерживаются на каждом узле. Для буферных таблиц их нужно явно создавать на каждом узле.