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

Вставка данных в ClickHouse

Основной пример

Вы можете использовать знакомую команду INSERT INTO TABLE в ClickHouse. Давайте вставим некоторые данные в таблицу, которую мы создали в стартовом руководстве "Создание таблиц в 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

Который возвращает:

user_id message                                             timestamp           metric
101         Hello, ClickHouse!                                  2024-11-13 20:01:22     -1
101         Granules are the smallest chunks of data read           2024-11-13 20:01:27 3.14159
102         Insert a lot of rows per batch                          2024-11-12 00:00:00 1.41421
102         Sort your data based on your commonly-used queries  2024-11-13 00:00:00     2.718

Вставка в ClickHouse против OLTP баз данных

Как OLAP (Online Analytical Processing) база данных, ClickHouse оптимизирован для высокой производительности и масштабируемости, что позволяет вставлять потенциально миллионы строк в секунду. Это достигается за счет сочетания высоко параллелизованной архитектуры и эффективного столбцового сжатия, но с компромиссами по немедленной согласованности. Более конкретно, ClickHouse оптимизирован для операций только по добавлению и предлагает только гарантии конечной согласованности.

В отличие от этого, OLTP базы данных, такие как Postgres, специально оптимизированы для транзакционных вставок с полным соблюдением ACID, что обеспечивает сильные гарантии согласованности и надежности. PostgreSQL использует MVCC (Multi-Version Concurrency Control) для обработки параллельных транзакций, что связано с поддержкой нескольких версий данных. Эти транзакции могут потенциально задействовать небольшое количество строк за раз, с значительными накладными расходами, связанными с гарантией надежности, которые ограничивают производительность вставок.

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

Наилучшие практики для вставок

Вставка большими пакетами

По умолчанию каждая вставка, отправленная в ClickHouse, вызывает немедленное создание части хранилища, содержащей данные вставки вместе с другой метаинформацией, которую нужно сохранить. Поэтому отправка меньшего количества вставок, каждая из которых содержит больше данных, по сравнению с отправкой большего количества вставок, каждая из которых содержит меньше данных, уменьшит количество необходимых записей. Обычно мы рекомендуем вставлять данные в достаточно крупных пакетах, как минимум по 1,000 строк за раз, а в идеале от 10,000 до 100,000 строк. (Дополнительные детали здесь).

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

Обеспечьте согласованные пакеты для идемпотентных повторений

По умолчанию вставки в ClickHouse являются синхронными и идемпотентными (т.е. выполнение одной и той же операции вставки несколько раз имеет тот же эффект, что и выполнение её один раз). Для таблиц семейства движка MergeTree ClickHouse по умолчанию автоматически дедуплицирует вставки.

Это означает, что вставки остаются устойчивыми в следующих случаях:

    1. Если узел, получающий данные, имеет проблемы, запрос вставки истечет по времени (или даст более специфическую ошибку) и не получит подтверждение.
    1. Если данные были записаны узлом, но подтверждение не может быть возвращено отправителю запроса из-за сетевых перебоев, отправитель либо получит тайм-аут, либо ошибку сети.

С точки зрения клиента (i) и (ii) могут быть сложно различить. Однако в обоих случаях неподтвержденную вставку можно немедленно повторить. Если повторяемый запрос вставки содержит те же данные в том же порядке, ClickHouse автоматически проигнорирует повторяемую вставку, если (неподтвержденная) оригинальная вставка удалась.

Вставка в таблицу MergeTree или распределённую таблицу

Мы рекомендуем вставлять данные непосредственно в MergeTree (или Реплицированную таблицу), балансируя запросы по набору узлов, если данные распределены, и устанавливая internal_replication=true. Это позволит ClickHouse реплицировать данные на любые доступные шардированные реплики и обеспечить конечную согласованность данных.

Если такая балансировка нагрузки на стороне клиента неудобна, пользователи могут вставлять данные через распределённую таблицу, которая затем распределяет записи между узлами. Снова рекомендуется установить internal_replication=true. Однако стоит отметить, что этот подход немного менее производителен, так как записи должны выполняться локально на узле с распределённой таблицей, а затем отправляться на шардированные реплики.

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

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

С включенными асинхронными вставками данные сначала вставляются в буфер, а затем записываются в хранилище базы данных позже в 3 этапа, как показано на диаграмме ниже:

Postgres inserts

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

(1) получает запрос вставки асинхронно.
(2) сначала записывает данные запроса в буфер в памяти.
(3) сортирует и записывает данные как часть в хранилище базы данных, только когда происходит следующий сброс буфера.

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

примечание

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

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

Используйте официальные клиенты ClickHouse

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

Смотрите Клиенты и Драйверы для полного списка доступных клиентов и драйверов ClickHouse.

Предпочитайте нативный формат

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

Для приложений, стремящихся достичь оптимальной производительности вставок, пользователи должны вставлять данные, используя Native формат. Этот формат поддерживается большинством клиентов (таких как Go и Python) и обеспечивает минимальные накладные расходы на сервер, поскольку этот формат уже является столбцовым. Тем самым ответственность за преобразование данных в столбцовый формат возлагается на клиентскую сторону. Это важно для эффективного масштабирования вставок.

В качестве альтернативы пользователи могут использовать RowBinary format (как используется Java клиентом), если предпочтителен строковый формат - он обычно легче для записи, чем нативный формат. Это более эффективно с точки зрения сжатия, сетевых накладных расходов и обработки на сервере по сравнению с альтернативными строковыми форматами, такими как JSON. Формат JSONEachRow может быть рассмотрен пользователями с низкой пропускной способностью записи, стремящимися к быстрому интеграции. Пользователи должны быть осведомлены о том, что этот формат повлечет за собой накладные расходы на CPU в ClickHouse для разбора.

Используйте HTTP интерфейс

В отличие от многих традиционных баз данных, ClickHouse поддерживает HTTP интерфейс. Пользователи могут использовать его как для вставки, так и для запроса данных, используя любой из вышеописанных форматов. Это часто предпочтительнее, чем родной протокол ClickHouse, так как позволяет легко переключать трафик с помощью балансировщиков нагрузки. Мы ожидаем небольшие отличия в производительности вставки с родным протоколом, который имеет немного меньшие накладные расходы. Существующие клиенты используют любой из этих протоколов (в некоторых случаях оба, например, Go клиент). Родной протокол позволяет легко отслеживать прогресс запроса.

Смотрите HTTP интерфейс для получения дополнительных деталей.

Загрузка данных из Postgres

Для загрузки данных из Postgres пользователи могут использовать:

  • PeerDB by ClickHouse, инструмент ETL, специально разработанный для репликации баз данных PostgreSQL. Он доступен как в:
  • Движок таблиц PostgreSQL для чтения данных прямо, как показано в предыдущих примерах. Обычно это подходит, если пакетная репликация, основанная на известном водоразделе, например, по времени, достаточна или если это одноразовая миграция. Этот подход может масштабироваться до десятков миллионов строк. Пользователи, стремящиеся мигрировать более крупные наборы данных, должны рассмотреть возможность нескольких запросов, каждый из которых обрабатывает часть данных. Временные таблицы могут использоваться для каждой части перед перемещением её партиций в финальную таблицу. Это позволяет повторно пытаться неудачные запросы. Для получения дополнительных деталей о стратегии массовой загрузки смотрите здесь.
  • Данные могут быть экспортированы из PostgreSQL в формате CSV. Эти данные затем могут быть вставлены в ClickHouse из локальных файлов или через объектное хранилище, используя табличные функции.
Нужна помощь с вставкой больших наборов данных?

Если вам нужна помощь с вставкой больших наборов данных или вы столкнулись с ошибками при импортировании данных в ClickHouse Cloud, пожалуйста, свяжитесь с нами по адресу support@clickhouse.com, и мы окажем помощь.