Обзор
- Использует
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(_). Если эта возможность включена,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
wa-37420. Примечание: эту возможность не следует использовать с более новыми версиями ClickHouse.
Примеры
Использование
Крейт ch2rs полезен для генерации типа строки на основе данных из ClickHouse.
Создание экземпляра клиента
Подключение по HTTPS или к ClickHouse Cloud
rustls-tls и native-tls.
Затем создайте клиент как обычно. В этом примере переменные окружения используются для хранения сведений о подключении:
- Пример 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.
Вставка строк
- Если
end()не вызвать,INSERTбудет прерван. - Строки отправляются постепенно, в виде потока, чтобы распределить нагрузку на сеть.
- ClickHouse выполняет атомарную вставку батчей, только если все строки помещаются в одну и ту же партицию и их количество меньше
max_insert_block_size.
Асинхронная вставка (батчинг на стороне сервера)
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, можно задать session_id, чтобы выполнять команды в рамках одного сеанса. session_id можно задать либо глобально на уровне клиента, либо для отдельных вызовов query, insert или inserter.
В кластерных развертываниях из-за отсутствия “sticky sessions” для корректного использования этой возможности нужно подключаться к конкретному узлу кластера, поскольку, например, балансировщик нагрузки 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или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пока не поддерживаются.
Мокирование
SELECT, INSERT и WATCH. Эту функциональность можно включить, активировав возможность test-util. Используйте её только как зависимость для разработки.
См. пример.
Устранение неполадок
CANNOT_READ_ALL_DATA
CANNOT_READ_ALL_DATA заключается в том, что определение строки на стороне приложения не совпадает с определением в ClickHouse.
Рассмотрим следующую таблицу:
EventLog определён на стороне приложения с несовпадающими типами, например:
EventLog:
Известные ограничения
- Типы данных
Variant,Dynamic, (new)JSONпока не поддерживаются. - Привязка параметров на стороне сервера пока не поддерживается; отслеживать статус можно в этой задаче.