Обзор
- Использует
serdeдля кодирования и декодирования строк. - Поддерживает атрибуты
serde:skip_serializing,skip_deserializing,rename. - Использует формат
RowBinaryпо HTTP.- В будущем планируется перейти на
Nativeпо TCP.
- В будущем планируется перейти на
- Поддерживает TLS (через возможности
native-tlsиrustls-tls). - Поддерживает сжатие и декомпрессию (LZ4).
- Предоставляет API для выборки и вставки данных, выполнения DDL-запросов и клиентского батчинга.
- Предоставляет удобные моки для модульного тестирования.
Установка
Cargo.toml:
Возможности Cargo
lz4(включена по умолчанию) — включает вариантыCompression::Lz4иCompression::Lz4Hc(_). Если эта возможность включена, то по умолчанию для всех запросов, кромеWATCH, используетсяCompression::Lz4.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
wa-37420. Примечание: эту возможность не следует использовать с более новыми версиями ClickHouse.
Примеры
Использование
Крейт ch2rs позволяет генерировать тип строки из ClickHouse.
Создание экземпляра клиента
HTTPS или подключение к ClickHouse Cloud
rustls-tls и native-tls.
Затем создайте клиент как обычно. В этом примере переменные окружения используются для хранения сведений о подключении:
- пример использования 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 тоже может быть полезен.
Вставка строк
- Если
end()не вызвать,INSERTбудет прерван. - Строки отправляются постепенно, в виде потока, чтобы распределить сетевую нагрузку.
- ClickHouse выполняет атомарную вставку батчей только в том случае, если все строки попадают в одну и ту же партицию, а их количество меньше
max_insert_block_size.
Async insert (батчинг на стороне сервера)
async_insert в метод insert (или даже самому экземпляру Client, чтобы она применялась ко всем вызовам insert).
- Пример async insert в репозитории клиента.
Возможность Inserter (батчинг на стороне клиента)
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.
Выполнение DDL-запросов
wait_end_of_query. Это можно сделать так:
Настройки 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.
В кластерных развертываниях из-за отсутствия “липких сеансов” для корректного использования этой возможности нужно подключаться к определённому узлу кластера, поскольку, например, балансировщик нагрузки round-robin не гарантирует, что последующие запросы будут обрабатываться одним и тем же узлом ClickHouse.
Произвольные HTTP-заголовки
Пользовательский 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.
IPv6преобразуется в/изstd::net::Ipv6Addr.IPv4преобразуется в/изstd::net::Ipv4Addrс помощьюserde::ipv4.
Dateпреобразуется в/изu16или newtype-обёртки вокруг него и представляет количество дней, прошедших с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или newtype-обёртки вокруг него и представляет время, прошедшее с эпохи UNIX. Также поддерживаетсяtime::OffsetDateTimeпри использованииserde::time::datetime64::*; для этого требуется возможностьtime.
Tuple(A, B, ...)преобразуется в/из(A, B, ...)или в/из newtype-обёртки над ним.Array(_)преобразуется в/из любого среза, напримерVec<_>,&[_]. New types тоже поддерживаются.Map(K, V)ведёт себя какArray((K, V)).LowCardinality(_)поддерживается без каких-либо сложностей.Nullable(_)преобразуется в/изOption<_>. Для вспомогательных средствclickhouse::serde::*добавьте::option.
Nestedподдерживается через указание нескольких массивов с переименованием.
- Поддерживаются типы
Geo.Pointпредставляет собой кортеж(f64, f64), а все остальные типы — это просто срезы точек.
- Типы данных
Variant,Dynamicи (новый)JSONпока не поддерживаются.
Имитация
SELECT, INSERT и WATCH. Эта функциональность включается с помощью возможности test-util. Используйте её только как зависимость для разработки.
См. пример.
Устранение неполадок
CANNOT_READ_ALL_DATA
CANNOT_READ_ALL_DATA заключается в том, что описание строки на стороне приложения не совпадает с описанием в ClickHouse.
Рассмотрим следующую таблицу:
EventLog определён на стороне приложения с типами, которые не совпадают, например:
EventLog:
Известные ограничения
- Типы данных
Variant,Dynamic, (new)JSONпока не поддерживаются. - Привязка параметров на стороне сервера пока не поддерживается; статус можно отслеживать в этой задаче.