Skip to main content
Официальный клиент ClickHouse для Rust, изначально разработанный Paul Loyd. Исходный код клиента доступен в репозитории GitHub.

Обзор

  • Использует serde для кодирования и декодирования строк.
  • Поддерживает атрибуты serde: skip_serializing, skip_deserializing, rename.
  • Использует формат RowBinary поверх HTTP-транспорта.
    • Планируется переход на Native поверх TCP.
  • Поддерживает TLS (через возможности native-tls и rustls-tls).
  • Поддерживает сжатие и распаковку (LZ4).
  • Предоставляет API для выборки и вставки данных, выполнения DDL-запросов и батчинга на стороне клиента.
  • Предоставляет удобные моки для модульного тестирования.

Установка

Чтобы использовать крейт, добавьте следующее в Cargo.toml:
См. также: страница на crates.io.

Возможности Cargo

  • lz4 (включена по умолчанию) — включает варианты Compression::Lz4 и Compression::Lz4Hc(_). Если эта возможность включена, Compression::Lz4 по умолчанию используется для всех запросов, кроме WATCH.
  • native-tls — поддерживает URL со схемой HTTPS через hyper-tls, который собирается с OpenSSL.
  • rustls-tls — поддерживает URL со схемой HTTPS через hyper-rustls, который не собирается с OpenSSL.
  • inserter — включает client.inserter().
  • test-util — добавляет моки. См. пример. Используйте только в dev-dependencies.
  • watch — включает функциональность client.watch. Подробности см. в соответствующем разделе.
  • uuid — добавляет serde::uuid для работы с крейтом uuid.
  • time — добавляет serde::time для работы с крейтом time.
При подключении к ClickHouse через URL с HTTPS должна быть включена одна из возможностей: native-tls или rustls-tls. Если включены обе, приоритет будет у возможности rustls-tls.

Совместимость версий ClickHouse

Клиент совместим с LTS-версиями ClickHouse и более новыми версиями, а также с ClickHouse Cloud. ClickHouse server версий ниже v22.6 в некоторых редких случаях некорректно обрабатывает RowBinary. Чтобы решить эту проблему, можно использовать v0.11+ и включить возможность wa-37420. Примечание: эту возможность не следует использовать с более новыми версиями ClickHouse.

Примеры

Мы стараемся охватить различные сценарии использования клиента в примерах в репозитории клиента. Обзор доступен в README с примерами. Если в примерах или в приведённой ниже документации что-то неясно или чего-то не хватает, свяжитесь с нами.

Использование

Крейт ch2rs полезен для генерации типа строки на основе данных из ClickHouse.

Создание экземпляра клиента

Повторно используйте созданные клиенты или клонируйте их, чтобы использовать общий базовый пул соединений hyper.

Подключение по HTTPS или к ClickHouse Cloud

HTTPS работает с возможностями Cargo rustls-tls и native-tls. Затем создайте клиент как обычно. В этом примере переменные окружения используются для хранения сведений о подключении:
URL должен включать и протокол, и порт, например https://instance.clickhouse.cloud:8443.
См. также:
  • Пример HTTPS с ClickHouse Cloud в репозитории client. Это также применимо к HTTPS-подключениям в собственной инфраструктуре.

Выборка строк

  • Плейсхолдер ?fields заменяется на no, name (поля Row).
  • Плейсхолдер ? заменяется значениями в последующих вызовах bind().
  • Для получения первой строки или всех строк соответственно можно использовать удобные методы fetch_one::<Row>() и fetch_all::<Row>().
  • sql::Identifier можно использовать для подстановки имён таблиц.
Примечание: поскольку весь ответ передаётся в потоковом режиме, курсоры могут возвращать ошибку даже после выдачи некоторых строк. Если в вашем случае это происходит, попробуйте query(...).with_option("wait_end_of_query", "1"), чтобы включить буферизацию ответа на стороне сервера. Подробнее. Также может быть полезен параметр buffer_size.
Используйте wait_end_of_query с осторожностью при выборке строк, так как это может привести к повышенному потреблению памяти на стороне сервера и, вероятно, снизит общую производительность.

Вставка строк

  • Если end() не вызвать, INSERT будет прерван.
  • Строки отправляются постепенно, в виде потока, чтобы распределить нагрузку на сеть.
  • ClickHouse выполняет атомарную вставку батчей, только если все строки помещаются в одну и ту же партицию и их количество меньше max_insert_block_size.

Асинхронная вставка (батчинг на стороне сервера)

Вы можете использовать асинхронные вставки ClickHouse, чтобы избежать батчинга входящих данных на стороне клиента. Для этого достаточно просто передать параметр async_insert методу insert (или даже самому экземпляру Client, чтобы это применялось ко всем вызовам insert).
См. также:

Возможность Inserter (батчинг на стороне клиента)

Требуется возможность Cargo inserter.
  • Inserter завершает активную вставку в commit(), если достигнут любой из порогов (max_bytes, max_rows, period).
  • Интервал между завершениями активных INSERT можно сместить с помощью with_period_bias, чтобы избежать пиков нагрузки при параллельной работе Inserter.
  • Inserter::time_left() можно использовать, чтобы определить, когда закончится текущий период. Если ваш поток редко выдает элементы, снова вызовите Inserter::commit(), чтобы проверить ограничения.
  • Пороги по времени реализованы с использованием крейта quanta, чтобы ускорить работу inserter. Не используется, если включен test-util (поэтому в пользовательских тестах временем можно управлять через tokio::time::advance()).
  • Все строки между вызовами commit() вставляются одним оператором INSERT.
Не забудьте выполнить flush, если хотите завершить/финализировать вставку:

Выполнение DDL-запросов

Для одноузлового развертывания достаточно выполнять DDL-запросы так:
Однако в кластерных развертываниях с балансировщиком нагрузки или в ClickHouse Cloud рекомендуется дождаться, пока DDL применится на всех репликах, используя параметр wait_end_of_query. Это можно сделать так:

Настройки ClickHouse

Вы можете применять различные настройки ClickHouse с помощью метода with_option. Например:
Помимо query, это аналогично работает и с методами insert и inserter; кроме того, тот же метод можно вызвать у экземпляра Client, чтобы задать глобальные настройки для всех запросов.

Query id

С помощью .with_option можно задать параметр query_id для идентификации запросов в журнале запросов ClickHouse.
Помимо query, это работает аналогичным образом и для методов insert и inserter.
Если вы задаёте query_id вручную, убедитесь, что он уникален. Для этого хорошо подходят UUID.
См. также: пример query_id в репозитории клиента.

Идентификатор сеанса

Как и в случае с query_id, можно задать session_id, чтобы выполнять команды в рамках одного сеанса. session_id можно задать либо глобально на уровне клиента, либо для отдельных вызовов query, insert или inserter.
В кластерных развертываниях из-за отсутствия “sticky sessions” для корректного использования этой возможности нужно подключаться к конкретному узлу кластера, поскольку, например, балансировщик нагрузки round-robin не гарантирует, что последующие запросы будут обрабатываться одним и тем же узлом ClickHouse.
См. также: пример session_id в репозитории клиента.

Пользовательские HTTP-заголовки

Если вы используете аутентификацию через прокси или вам нужно передать пользовательские заголовки, это можно сделать так:
См. также: пример использования пользовательских HTTP-заголовков в репозитории client.

Собственный HTTP-клиент

Это может быть полезно для настройки параметров используемого пула HTTP-соединений.
В этом примере используется устаревший API Hyper, и в будущем он может измениться.
См. также: пример пользовательского HTTP-клиента в репозитории клиента.

Типы данных

  • (U)Int(8|16|32|64|128) сопоставляется с соответствующими типами (u|i)(8|16|32|64|128) или типами newtype-обёртка на их основе и обратно.
  • (U)Int256 напрямую не поддерживаются, но для них есть обходное решение.
  • Float(32|64) сопоставляется с соответствующими f(32|64) или типами newtype-обёртка на их основе и обратно.
  • Decimal(32|64|128) сопоставляется с соответствующими i(32|64|128) или типами newtype-обёртка на их основе и обратно. Удобнее использовать fixnum или другую реализацию знаковых чисел с фиксированной запятой.
  • Boolean сопоставляется с bool или типами newtype-обёртка на его основе и обратно.
  • String сопоставляется с любыми строковыми или байтовыми типами и обратно, например &str, &[u8], String, Vec<u8> или SmartString. Пользовательские типы тоже поддерживаются. Для хранения байтов рекомендуется использовать serde_bytes, поскольку это эффективнее.
  • FixedString(N) поддерживается в виде массива байтов, например [u8; N].
  • Enum(8|16) поддерживается с помощью serde_repr.
  • UUID преобразуется в/из uuid::Uuid с помощью serde::uuid. Для этого требуется возможность uuid.
  • Date преобразуется в/из u16 или newtype-обёртку на его основе и представляет собой количество дней, прошедших с 1970-01-01. Также поддерживается time::Date через serde::time::date, для чего требуется возможность time.
  • Date32 преобразуется в/из i32 или newtype-обёртку на его основе и представляет количество дней, прошедших с 1970-01-01. Также поддерживается time::Date через serde::time::date32; для этого требуется возможность time.
  • DateTime сопоставляется с u32 и обратно, либо с newtype-обёрткой над ним, и представляет собой количество секунд, прошедших с эпохи Unix. Также поддерживается time::OffsetDateTime через serde::time::datetime, для чего требуется возможность time.
  • DateTime64(_) преобразуется в/из i32 или newtype, оборачивающий его, и представляет время, прошедшее с эпохи Unix. Также поддерживается time::OffsetDateTime при использовании serde::time::datetime64::*; для этого требуется возможность time.
  • Tuple(A, B, ...) преобразуется в (A, B, ...) и обратно, либо в newtype-обёртку над ним.
  • Array(_) преобразуется в любой срез и обратно, например Vec<_>, &[_]. Также поддерживаются новые типы.
  • Map(K, V) ведёт себя как Array((K, V)).
  • LowCardinality(_) поддерживается прозрачно.
  • Nullable(_) преобразуется в Option<_> и обратно. Для хелперов clickhouse::serde::* добавьте ::option.
  • Nested поддерживается через передачу нескольких массивов с переименованием.
  • Поддерживаются типы Geo. Point ведёт себя как кортеж (f64, f64), а остальные типы — это просто срезы точек.
  • Типы данных Variant, Dynamic и (новый) JSON пока не поддерживаются.

Мокирование

Крейт предоставляет утилиты для мокирования сервера CH и тестирования запросов DDL, SELECT, INSERT и WATCH. Эту функциональность можно включить, активировав возможность test-util. Используйте её только как зависимость для разработки. См. пример.

Устранение неполадок

CANNOT_READ_ALL_DATA

Наиболее частая причина ошибки CANNOT_READ_ALL_DATA заключается в том, что определение строки на стороне приложения не совпадает с определением в ClickHouse. Рассмотрим следующую таблицу:
Затем, если EventLog определён на стороне приложения с несовпадающими типами, например:
При вставке данных может возникнуть следующая ошибка:
В этом примере проблема исправляется правильным определением структуры EventLog:

Известные ограничения

  • Типы данных Variant, Dynamic, (new) JSON пока не поддерживаются.
  • Привязка параметров на стороне сервера пока не поддерживается; отслеживать статус можно в этой задаче.

Свяжитесь с нами

Если у вас есть вопросы или вам нужна помощь, обращайтесь к нам в Community Slack или через GitHub Issues.
Последнее изменение 23 июля 2026 г.