Перейти к основному содержимому
Перейти к основному содержимому

Выбор стратегии вставки

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

примечание

Следующее предполагает, что вы передаете данные в ClickHouse через клиент. Если вы загружаете данные в ClickHouse, например, с помощью встроенных табличных функций, таких как s3 и gcs, мы рекомендуем ознакомиться с нашим руководством "Оптимизация производительности вставок и чтений для S3".

Синхронные вставки по умолчанию

По умолчанию вставки в ClickHouse являются синхронными. Каждый запрос вставки немедленно создает часть хранения на диске, включая метаданные и индексы.

Используйте синхронные вставки, если вы можете пакетировать данные на стороне клиента

Если нет, смотрите Асинхронные вставки ниже.

Мы кратко рассмотрим механику вставок в MergeTree ClickHouse ниже:

Шаги на стороне клиента

Для достижения оптимальной производительности данные должны быть ①пакетированы, что делает размер пакета первым решением.

ClickHouse хранит вставленные данные на диске,упорядоченные по столбцу(ам) первичного ключа таблицы. Второе решение заключается в том, чтобы ② предварительно отсортировать данные перед передачей серверу. Если пакет приходит предварительно отсортированным по столбцу(ам) первичного ключа, ClickHouse может пропустить ⑨ шаг сортировки, ускоряя прием.

Если данные для вставки не имеют предопределенного формата, ключевое решение заключается в выборе формата. ClickHouse поддерживает вставку данных в более чем 70 форматах. Однако при использовании клиентской командной строки ClickHouse или клиентов на языках программирования этот выбор часто обрабатывается автоматически. При необходимости этот автоматический выбор также можно явно переопределить.

Следующее значительное решение — это ④ следует ли сжимать данные до передачи серверу ClickHouse. Сжатие уменьшает размер передачи и улучшает сетевую эффективность, что приводит к более быстрому трансферу данных и меньшему использованию пропускной способности, особенно для больших наборов данных.

Данные ⑤ передаются на сетевой интерфейс ClickHouse - либо на native, либо на HTTP интерфейс (который мы сравниваем позже в этом посте).

Шаги на стороне сервера

После ⑥ получения данных ClickHouse ⑦ распаковывает их, если сжатие использовалось, затем ⑧ разбирает их из исходного формата.

Используя значения из этих отформатированных данных и оператор DDL целевой таблицы, ClickHouse ⑨ строит в памяти блок в формате MergeTree, ⑩ сортирует строки по столбцам первичного ключа, если они еще не отсортированы, ⑪ создает разреженный первичный индекс, ⑫ применяет сжатие по столбцам и ⑬ записывает данные как новую ⑭ часть данных на диск.

Пакетные вставки, если синхронные

The above mechanics illustrate a constant overhead regardless of the insert size, making batch size the single most important optimization for ingest throughput. Batching inserts reduce the overhead as a proportion of total insert time and improves processing efficiency.

We recommend inserting data in batches of at least 1,000 rows, and ideally between 10,000–100,000 rows. Fewer, larger inserts reduce the number of parts written, minimize merge load, and lower overall system resource usage.

For a synchronous insert strategy to be effective this client-side batching is required.

If you're unable to batch data client-side, ClickHouse supports asynchronous inserts that shift batching to the server (see).

подсказка

Regardless of the size of your inserts, we recommend keeping the number of insert queries around one insert query per second. The reason for that recommendation is that the created parts are merged to larger parts in the background (in order to optimize your data for read queries), and sending too many insert queries per second can lead to situations where the background merging can't keep up with the number of new parts. However, you can use a higher rate of insert queries per second when you use asynchronous inserts (see asynchronous inserts).

Обеспечьте идемпотентные повторные попытки

Синхронные вставки также являются идемпотентными. При использовании движков MergeTree ClickHouse будет дедуплицировать вставки по умолчанию. Это защищает от неоднозначных случаев сбоев, таких как:

  • Вставка прошла успешно, но клиент никогда не получил подтверждение из-за сетевого прерывания.
  • Вставка завершилась неудачей на стороне сервера и превысила время ожидания.

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

Выберите правильное место вставки

Для шардированных кластеров у вас есть два варианта:

  • Вставьте напрямую в таблицу MergeTree или ReplicatedMergeTree. Это наиболее эффективный вариант, когда клиент может выполнять балансировку нагрузки между шардми. При internal_replication = true ClickHouse обрабатывает репликацию прозрачно.
  • Вставка в Распределенную таблицу. Это позволяет клиентам отправлять данные на любой узел и позволить ClickHouse перенаправить их на правильный шард. Это проще, но немного менее эффективно из-за дополнительного шага перенаправления. Рекомендуется также internal_replication = true.

В ClickHouse Cloud все узлы читают и записывают в один и тот же шард. Вставки автоматически сбалансированы между узлами. Пользователи могут просто отправлять вставки на открытый конечный пункт.

Выберите правильный формат

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

Хотя гибкость полезна для обработки данных и импорта на основе файлов, приложения должны приоритизировать форматы, ориентированные на производительность:

  • Нативный формат (рекомендуется): Наиболее эффективный. Столбцовый, требует минимального разбора на стороне сервера. Используется по умолчанию в клиентах Go и Python.
  • RowBinary: Эффективный строковый формат, идеален, если столбцовая трансформация сложна на стороне клиента. Используется клиентом Java.
  • JSONEachRow: Легок в использовании, но дорогостоящ в разборе. Подходит для случаев с низким объемом данных или быстрых интеграций.

Используйте сжатие

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

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

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

Используйте LZ4 для скорости, ZSTD для соотношения сжатия

ClickHouse поддерживает несколько кодеков сжатия во время передачи данных. Две распространенные опции:

  • LZ4: Быстрый и легковесный. Существенно уменьшает размер данных с минимальными накладными расходами на CPU, что делает его идеальным для вставок с высокой пропускной способностью и по умолчанию в большинстве клиентов ClickHouse.
  • ZSTD: Более высокое соотношение сжатия, но более ресурсоемкий для CPU. Полезно, когда затраты на передачу по сети высоки — такие как в сценариях с межрегиональной передачей или при использовании облачных провайдеров, хотя это немного увеличивает время вычислений на стороне клиента и время распаковки на стороне сервера.

Рекомендация по лучшим практикам: Используйте LZ4, если только у вас нет ограниченной пропускной способности или если вы не несете затраты на исходящие данные — тогда рассмотрите возможность использования ZSTD.

примечание

В тестах из бенчмарка FastFormats вставки, сжатые с помощью LZ4, уменьшили размер данных более чем на 50%, сократив время приема с 150s до 131s для набора данных размером 5.6 GiB. Переход на ZSTD сжал тот же набор данных до 1.69 GiB, но немного увеличил время обработки на стороне сервера.

Сжатие снижает использование ресурсов

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

Влияние сжатия на CPU и память невелико для LZ4 и умеренное для ZSTD. Даже под нагрузкой эффективность на стороне сервера улучшается за счет уменьшенного объема данных.

Комбинирование сжатия с пакетированием и эффективным форматом ввода (таким как Нативный) приводит к лучшей производительности приема.

При использовании нативного интерфейса (например, clickhouse-client) сжатие LZ4 включает по умолчанию. Вы также можете при необходимости переключиться на ZSTD через настройки.

С HTTP интерфейсом используйте заголовок Content-Encoding, чтобы применить сжатие (например, Content-Encoding: lz4). Вся полезная нагрузка должна быть сжата перед отправкой.

Предварительная сортировка при низкой стоимости

Предварительная сортировка данных по первичному ключу перед вставкой может повысить эффективность приема в ClickHouse, особенно для больших пакетов.

Когда данные приходят предварительно отсортированными, ClickHouse может пропустить или упростить внутренний шаг сортировки при создании части, снижая использование CPU и ускоряя процесс вставки. Предварительная сортировка также улучшает эффективность сжатия, поскольку похожие значения группируются вместе - позволяя кодекам, таким как LZ4 или ZSTD, достигать лучшего соотношения сжатия. Это особенно полезно в сочетании с крупными пакетными вставками и сжатием, поскольку снижает как затраты на обработку, так и объем передаваемых данных.

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

Мы рекомендуем предварительную сортировку только в том случае, если данные уже почти отсортированы или если ресурсы на стороне клиента (CPU, память) достаточны и недостаточно используются. В ситуациях, чувствительных к задержкам или с высокой пропускной способностью, таких как мониторинг, когда данные приходят не в порядке или от множества агентов, часто лучше пропустить предварительную сортировку и полагаться на встроенную производительность ClickHouse.

Асинхронные вставки

Asynchronous inserts in ClickHouse provide a powerful alternative when client-side batching isn't feasible. This is especially valuable in observability workloads, where hundreds or thousands of agents send data continuously - logs, metrics, traces - often in small, real-time payloads. Buffering data client-side in these environments increases complexity, requiring a centralized queue to ensure sufficiently large batches can be sent.

примечание

Sending many small batches in synchronous mode is not recommended, leading to many parts being created. This will lead to poor query performance and "too many part" errors.

Asynchronous inserts shift batching responsibility from the client to the server by writing incoming data to an in-memory buffer, then flushing it to storage based on configurable thresholds. This approach significantly reduces part creation overhead, lowers CPU usage, and ensures ingestion remains efficient - even under high concurrency.

The core behavior is controlled via the async_insert setting.

When enabled (1), inserts are buffered and only written to disk once one of the flush conditions is met:

(1) the buffer reaches a specified size (async_insert_max_data_size) (2) a time threshold elapses (async_insert_busy_timeout_ms) or (3) a maximum number of insert queries accumulate (async_insert_max_query_number).

This batching process is invisible to clients and helps ClickHouse efficiently merge insert traffic from multiple sources. However, until a flush occurs, the data cannot be queried. Importantly, there are multiple buffers per insert shape and settings combination, and in clusters, buffers are maintained per node - enabling fine-grained control across multi-tenant environments. Insert mechanics are otherwise identical to those described for synchronous inserts.

Choosing a Return Mode

The behavior of asynchronous inserts is further refined using the wait_for_async_insert setting.

When set to 1 (the default), ClickHouse only acknowledges the insert after the data is successfully flushed to disk. This ensures strong durability guarantees and makes error handling straightforward: if something goes wrong during the flush, the error is returned to the client. This mode is recommended for most production scenarios, especially when insert failures must be tracked reliably.

Benchmarks show it scales well with concurrency - whether you're running 200 or 500 clients- thanks to adaptive inserts and stable part creation behavior.

Setting wait_for_async_insert = 0 enables "fire-and-forget" mode. Here, the server acknowledges the insert as soon as the data is buffered, without waiting for it to reach storage.

This offers ultra-low-latency inserts and maximal throughput, ideal for high-velocity, low-criticality data. However, this comes with trade-offs: there's no guarantee the data will be persisted, errors may only surface during flush, and it's difficult to trace failed inserts. Use this mode only if your workload can tolerate data loss.

Benchmarks also demonstrate substantial part reduction and lower CPU usage when buffer flushes are infrequent (e.g. every 30 seconds), but the risk of silent failure remains.

Our strong recommendation is to use async_insert=1,wait_for_async_insert=1 if using asynchronous inserts. Using wait_for_async_insert=0 is very risky because your INSERT client may not be aware if there are errors, and also can cause potential overload if your client continues to write quickly in a situation where the ClickHouse server needs to slow down the writes and create some backpressure in order to ensure reliability of the service.

Deduplication and reliability

By default, ClickHouse performs automatic deduplication for synchronous inserts, which makes retries safe in failure scenarios. However, this is disabled for asynchronous inserts unless explicitly enabled (this should not be enabled if you have dependent materialized views - see issue).

In practice, if deduplication is turned on and the same insert is retried - due to, for instance, a timeout or network drop - ClickHouse can safely ignore the duplicate. This helps maintain idempotency and avoids double-writing data. Still, it's worth noting that insert validation and schema parsing happen only during buffer flush - so errors (like type mismatches) will only surface at that point.

Enabling asynchronous inserts

Asynchronous inserts can be enabled for a particular user, or for a specific query:

  • Enabling asynchronous inserts at the user level. This example uses the user default, if you create a different user then substitute that username:

  • You can specify the asynchronous insert settings by using the SETTINGS clause of insert queries:

  • You can also specify asynchronous insert settings as connection parameters when using a ClickHouse programming language client.

    As an example, this is how you can do that within a JDBC connection string when you use the ClickHouse Java JDBC driver for connecting to ClickHouse Cloud :

Выберите интерфейс - HTTP или Native

Native

ClickHouse предлагает два основных интерфейса для приема данных: нативный интерфейс и HTTP интерфейс - каждый из которых имеет свои компромиссы между производительностью и гибкостью. Нативный интерфейс, используемый clickhouse-client и некоторыми языковыми клиентами, такими как Go и C++, создан специально для производительности. Он всегда передает данные в высокоэффективном Нативном формате ClickHouse, поддерживает пакетное сжатие с помощью LZ4 или ZSTD и минимизирует обработку на стороне сервера, перегружая такие задачи, как разбор и преобразование формата, на клиента.

Он даже позволяет выполнять вычисления на стороне клиента для значений MATERIALIZED и DEFAULT столбцов, позволяя серверу полностью пропускать эти шаги. Это делает нативный интерфейс идеальным для сценариев с высокой пропускной способностью, где эффективность критически важна.

HTTP

В отличие от многих традиционных баз данных, ClickHouse также поддерживает HTTP интерфейс. Это, наоборот, приоритизирует совместимость и гибкость. Он позволяет отправлять данные в любом поддерживаемом формате - включая JSON, CSV, Parquet и другие - и широко поддерживается большинством клиентов ClickHouse, включая Python, Java, JavaScript и Rust.

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

Тем не менее, он лишен более глубокой интеграции нативного протокола и не может выполнять оптимизации на стороне клиента, такие как вычисление значений материализованных или автоматическое преобразование в Нативный формат. Хотя вставки через HTTP можно сжимать с использованием стандартных HTTP заголовков (например, Content-Encoding: lz4), сжатие применяется ко всей полезной нагрузке, а не к отдельным блокам данных. Этот интерфейс часто предпочитается в средах, где простота протокола, балансировка нагрузки или широкая совместимость форматов важнее, чем сырая производительность.

Для более подробного описания этих интерфейсов смотрите здесь.