ClickHouse Rust Client
Официальный клиент Rust для подключения к ClickHouse, первоначально разработанный 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 версии старше v22.6 обрабатывает RowBinary неправильно в некоторых редких случаях.
Вы можете использовать v0.11+ и включить функцию wa-37420
, чтобы решить эту проблему. Примечание: использование этой функции с более новыми версиями ClickHouse не рекомендуется.
Примеры
Мы стремимся охватить различные сценарии использования клиента в примерах в репозитории клиента. Обзор доступен в README примеров.
Если что-то неясно или отсутствует в примерах или в следующей документации, не стесняйтесь связаться с нами.
Использование
Пакет ch2rs полезен для создания типа строки из ClickHouse.
Создание экземпляра клиента
Повторно используйте созданные клиенты или клонируйте их, чтобы повторно использовать базу соединений hyper.
Подключение через HTTPS или ClickHouse Cloud
HTTPS работает как с функциями rustls-tls
, так и native-tls
.
Затем создайте клиента как обычно. В этом примере переменные окружения используются для хранения данных подключения:
URL должен включать как протокол, так и порт, например, https://instance.clickhouse.cloud:8443
.
См. также:
- Пример HTTPS с ClickHouse Cloud в репозитории клиента. Это должно быть применимо и к локальным соединениям 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 (пакетирование на стороне клиента)
Требует функции inserter
в Cargo.
Inserter
завершает активную вставку вcommit()
, если какое-либо из пределов (max_bytes
,max_rows
,period
) достигнуты.- Интервал между завершением активных
INSERT
может быть скорректирован с помощьюwith_period_bias
, чтобы избежать пиков нагрузки в параллельных вставках. Inserter::time_left()
может быть использован для обнаружения, когда текущий период заканчивается. ВызовитеInserter::commit()
снова для проверки пределов, если ваш поток редко выдает элементы.- Порог времени реализован с помощью quanta пакета для ускорения
inserter
. Не используется, еслиtest-util
включен (в этом случае время может управляться с помощьюtokio::time::advance()
в пользовательских тестах). - Все строки между вызовами
commit()
вставляются в одномINSERT
запросе.
Не забудьте выполнить сброс, если хотите завершить вставку:
Выполнение DDL
Для развертывания на одном узле достаточно выполнить DDL так:
Однако, в кластерных развертываниях с балансировщиком нагрузки или ClickHouse Cloud рекомендуется дождаться применения DDL на всех репликах, используя опцию wait_end_of_query
. Это можно сделать так:
Настройки ClickHouse
Вы можете применять различные настройки ClickHouse с помощью метода with_option
. Например:
Кроме query
, он работает аналогично для методов insert
и inserter
; дополнительно, тот же метод можно вызывать на экземпляре Client
, чтобы задать глобальные настройки для всех запросов.
Идентификатор запроса
С помощью .with_option
вы можете установить опцию query_id
, чтобы идентифицировать запросы в журнале запросов ClickHouse.
Кроме query
, он работает аналогично для методов insert
и inserter
.
Если вы устанавливаете query_id
вручную, убедитесь, что он уникален. UUID являются хорошим выбором для этого.
См. также: пример query_id в репозитории клиента.
Идентификатор сессии
Аналогично query_id
, вы можете установить session_id
, чтобы выполнять инструкции в одной сессии. session_id
может быть установлен либо глобально на уровне клиента, либо для каждого вызова query
, insert
или inserter
.
В кластерных развертываниях, из-за отсутствия "липких сессий", вам нужно быть подключенным к определенному узлу кластера, чтобы правильно использовать эту функцию, поскольку, например, балансировщик нагрузки с круговым распределением не гарантирует, что последующие запросы будут обработаны тем же узлом ClickHouse.
См. также: пример session_id в репозитории клиента.
Пользовательские HTTP заголовки
Если вы используете аутентификацию прокси или необходимо передать пользовательские заголовки, это можно сделать так:
См. также: пример пользовательских HTTP заголовков в репозитории клиента.
Пользовательский HTTP клиент
Это может быть полезно для настройки параметров используемого пула HTTP соединений.
Этот пример основан на устаревшем API Hyper и может измениться в будущем.
См. также: пример пользовательского HTTP клиента в репозитории клиента.
Типы данных
См. также дополнительные примеры:
(U)Int(8|16|32|64|128)
сопоставляется с соответствующими типами(u|i)(8|16|32|64|128)
или новыми типами вокруг них.(U)Int256
не поддерживаются напрямую, но есть решение для этого.Float(32|64)
сопоставляется с соответствующимиf(32|64)
или новыми типами вокруг них.Decimal(32|64|128)
сопоставляется с соответствующимиi(32|64|128)
или новыми типами вокруг них. Удобнее использоватьfixnum
или другую реализацию знаковых фиксированных чисел с плавающей точкой.Boolean
сопоставляется сbool
или новыми типами вокруг него.String
сопоставляется с любыми строковыми или байтовыми типами, такими как&str
,&[u8]
,String
,Vec<u8>
илиSmartString
. Новые типы также поддерживаются. Для хранения байтов рассмотрите возможность использованияserde_bytes
, так как это более эффективно.
FixedString(N)
поддерживается как массив байтов, например,[u8; N]
.
Enum(8|16)
поддерживаются с использованиемserde_repr
.
UUID
сопоставляется сuuid::Uuid
с использованиемserde::uuid
. Требует включения функцииuuid
.
IPv6
сопоставляется сstd::net::Ipv6Addr
.IPv4
сопоставляется сstd::net::Ipv4Addr
с использованиемserde::ipv4
.
Date
сопоставляется сu16
или новым типом вокруг него и представляет собой количество дней, прошедших с1970-01-01
. Также поддерживаетсяtime::Date
с использованиемserde::time::date
, для этого требуется функцияtime
.
Date32
сопоставляется сi32
или новым типом вокруг него и представляет собой количество дней, прошедших с1970-01-01
. Также поддерживаетсяtime::Date
с использованиемserde::time::date32
, для этого требуется функцияtime
.
DateTime
сопоставляется сu32
или новым типом вокруг него и представляет собой количество секунд, прошедших с эпохи UNIX. Также поддерживаетсяtime::OffsetDateTime
с использованиемserde::time::datetime
, для этого требуется функцияtime
.
DateTime64(_)
сопоставляется сi32
или новым типом вокруг него и представляет собой время, прошедшее с эпохи UNIX. Также поддерживаетсяtime::OffsetDateTime
с использованиемserde::time::datetime64::*
, для этого требуется функцияtime
.
Tuple(A, B, ...)
сопоставляется с(A, B, ...)
или новым типом вокруг этого.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
. Используйте ее только в качестве dev-зависимости.
См. пример.
Устранение неполадок
CANNOT_READ_ALL_DATA
Наиболее распространенной причиной ошибки CANNOT_READ_ALL_DATA
является то, что определение строки на стороне приложения не совпадает с тем, что в ClickHouse.
Рассмотрим следующую таблицу:
Тогда, если EventLog
определен на стороне приложения с несовпадающими типами, например:
При вставке данных может возникнуть следующая ошибка:
В этом примере это исправляется правильным определением структуры EventLog
:
Известные ограничения
Variant
,Dynamic
, (новые)JSON
типы данных пока не поддерживаются.- Привязка параметров на стороне сервера пока не поддерживается; см. эту проблему для отслеживания.
Свяжитесь с нами
Если у вас есть вопросы или вам нужна помощь, не стесняйтесь обращаться к нам в Community Slack или через GitHub issues.