Skip to main content
O cliente oficial Rust para conectar ao ClickHouse, desenvolvido originalmente por Paul Loyd. O código-fonte do cliente está disponível no repositório do GitHub.

Visão geral

  • Usa serde para serializar/desserializar linhas.
  • Oferece suporte a atributos do serde: skip_serializing, skip_deserializing, rename.
  • Usa o formato RowBinary via transporte HTTP.
    • Há planos de migrar para Native via TCP.
  • Oferece suporte a TLS (por meio dos recursos native-tls e rustls-tls).
  • Oferece suporte a compressão e descompressão (LZ4).
  • Fornece APIs para consultar ou inserir dados, executar DDLs e fazer batching no lado do cliente.
  • Fornece mocks úteis para testes unitários.

Instalação

Para usar o crate, adicione o seguinte ao Cargo.toml:
Veja também: página no crates.io.

Features do Cargo

  • lz4 (habilitado por padrão) — habilita as variantes Compression::Lz4 e Compression::Lz4Hc(_). Quando habilitado, Compression::Lz4 é usado por padrão em todas as consultas, exceto em WATCH.
  • native-tls — oferece suporte a URLs com o esquema HTTPS via hyper-tls, que faz link com o OpenSSL.
  • rustls-tls — oferece suporte a URLs com o esquema HTTPS via hyper-rustls, que não faz link com o OpenSSL.
  • inserter — habilita client.inserter().
  • test-util — adiciona mocks. Veja o exemplo. Use-o apenas em dev-dependencies.
  • watch — habilita a funcionalidade client.watch. Consulte a seção correspondente para mais detalhes.
  • uuid — adiciona serde::uuid para trabalhar com a crate uuid.
  • time — adiciona serde::time para trabalhar com a crate time.
Ao se conectar ao ClickHouse por meio de uma URL HTTPS, é necessário habilitar a feature native-tls ou rustls-tls. Se ambos estiverem habilitados, a feature rustls-tls terá precedência.

Compatibilidade entre versões do ClickHouse

O cliente é compatível com versões LTS ou mais recentes do ClickHouse, bem como com o ClickHouse Cloud. O servidor ClickHouse anterior à v22.6 processa o RowBinary de forma incorreta em alguns casos raros. Você pode usar a v0.11+ e habilitar a feature wa-37420 para resolver esse problema. Observação: essa feature não deve ser usada com versões mais recentes do ClickHouse.

Exemplos

Nosso objetivo é abranger vários cenários de uso do cliente com os exemplos no repositório do cliente. A visão geral está disponível no README dos exemplos. Se algo não estiver claro ou estiver faltando nos exemplos ou na documentação a seguir, fique à vontade para entrar em contato conosco.

Uso

O crate ch2rs é útil para gerar um tipo de linha com base no ClickHouse.

Criando uma instância de cliente

Reutilize os clientes criados ou clone-os para aproveitar o pool de conexões subjacente do hyper.

Conexão HTTPS ou ClickHouse Cloud

O HTTPS funciona com as features rustls-tls ou native-tls do Cargo. Em seguida, crie o cliente como de costume. Neste exemplo, as variáveis de ambiente são usadas para armazenar os detalhes da conexão:
A URL deve incluir tanto o protocolo quanto a porta, por exemplo, https://instance.clickhouse.cloud:8443.
Veja também:

Selecionando linhas

  • O placeholder ?fields é substituído por no, name (campos de Row).
  • O placeholder ? é substituído pelos valores nas chamadas bind() a seguir.
  • Os métodos convenientes fetch_one::<Row>() e fetch_all::<Row>() podem ser usados para obter a primeira linha ou todas as linhas, respectivamente.
  • sql::Identifier pode ser usado para vincular nomes de tabelas.
NB: como toda a resposta é transmitida em streaming, os cursores podem retornar um erro mesmo depois de produzir algumas linhas. Se isso acontecer no seu caso de uso, você pode tentar query(...).with_option("wait_end_of_query", "1") para ativar a bufferização de resposta no servidor. Mais detalhes. A opção buffer_size também pode ser útil.
Use wait_end_of_query com cautela ao selecionar linhas, pois isso pode aumentar o consumo de memória no servidor e provavelmente reduzir o desempenho geral.

Inserindo linhas

  • Se end() não for chamado, o INSERT é abortado.
  • As linhas são enviadas progressivamente em stream para distribuir a carga na rede.
  • O ClickHouse realiza inserts em lote de forma atômica somente se todas as linhas couberem na mesma partição e se o número delas for menor que max_insert_block_size.

Async insert (batching no servidor)

Você pode usar inserções assíncronas do ClickHouse para evitar o batching no lado do cliente dos dados recebidos. Isso pode ser feito simplesmente fornecendo a opção async_insert ao método insert (ou até mesmo à própria instância Client, para que isso afete todas as chamadas de insert).
Veja também:

Funcionalidade Inserter (batching no lado do cliente)

Requer a feature inserter do Cargo.
  • Inserter encerra a inserção ativa em commit() se qualquer um dos limiares (max_bytes, max_rows, period) for atingido.
  • O intervalo entre o encerramento de INSERTs ativos pode receber um viés com with_period_bias para evitar picos de carga causados por insertores paralelos.
  • Inserter::time_left() pode ser usado para detectar quando o período atual termina. Chame Inserter::commit() novamente para verificar os limites se o seu fluxo emitir itens raramente.
  • Os limiares de tempo são implementados usando o crate quanta para acelerar o inserter. Ele não é usado se test-util estiver habilitado (assim, o tempo pode ser controlado por tokio::time::advance() em testes personalizados).
  • Todas as linhas entre chamadas de commit() são inseridas na mesma instrução INSERT.
Não se esqueça de fazer flush se quiser encerrar/finalizar a inserção:

Executando DDLs

Com uma implantação com um único nó, basta executar DDLs desta forma:
No entanto, em implantações com cluster e balanceador de carga, ou no ClickHouse Cloud, recomenda-se aguardar a aplicação do DDL em todas as réplicas usando a opção wait_end_of_query. Isso pode ser feito assim:

Configurações do ClickHouse

Você pode aplicar diversas configurações do ClickHouse usando o método with_option. Por exemplo:
Além de query, isso funciona de forma semelhante com os métodos insert e inserter; além disso, o mesmo método pode ser chamado na instância Client para definir configurações globais para todas as consultas.

ID da consulta

Com .with_option, você pode definir a opção query_id para identificar consultas no log de consultas do ClickHouse.
Além de query, isso também funciona de forma semelhante com os métodos insert e inserter.
Se você definir query_id manualmente, certifique-se de que ele seja único. UUIDs são uma boa opção para isso.
Veja também: exemplo de query_id no repositório do client.

ID da sessão

Assim como em query_id, você pode definir o session_id para executar as instruções na mesma sessão. O session_id pode ser definido globalmente no nível do cliente ou por chamada de query, insert ou inserter.
Em implantações em cluster, devido à falta de “afinidade de sessão”, você precisa estar conectado a um nó específico do cluster para usar esse recurso corretamente, pois, por exemplo, um balanceador de carga round-robin não garante que as solicitações subsequentes sejam processadas pelo mesmo nó do ClickHouse.
Veja também: exemplo de session_id no repositório do client.

Cabeçalhos HTTP personalizados

Se você estiver usando autenticação por proxy ou precisar enviar cabeçalhos personalizados, poderá fazer isso assim:
Veja também: exemplo de cabeçalhos HTTP personalizados no repositório do cliente.

Cliente HTTP personalizado

Isso pode ser útil para ajustar as configurações internas do pool de conexões HTTP.
Este exemplo depende da API Hyper legada e pode mudar no futuro.
Veja também: exemplo de cliente HTTP personalizado no repositório do client.

Tipos de dados

  • (U)Int(8|16|32|64|128) tem mapeamento de/para os tipos correspondentes (u|i)(8|16|32|64|128) ou newtypes baseados neles.
  • (U)Int256 não tem suporte direto, mas há uma solução alternativa.
  • Float(32|64) tem mapeamento de/para os correspondentes f(32|64) ou newtypes baseados neles.
  • Decimal(32|64|128) tem mapeamento de/para os correspondentes i(32|64|128) ou newtypes baseados neles. É mais prático usar fixnum ou outra implementação de números de ponto fixo com sinal.
  • Boolean tem mapeamento de/para bool ou newtypes baseados nele.
  • String tem mapeamento de/para qualquer tipo de string ou bytes, por exemplo, &str, &[u8], String, Vec<u8> ou SmartString. Novos tipos também têm suporte. Para armazenar bytes, considere usar serde_bytes, pois é mais eficiente.
  • FixedString(N) é suportado como um array de bytes, por exemplo [u8; N].
  • UUID é mapeado entre uuid::Uuid com o uso de serde::uuid. Requer a feature uuid.
  • Date é mapeado de/para u16 ou um newtype baseado nele e representa um número de dias decorridos desde 1970-01-01. Além disso, time::Date também é compatível usando serde::time::date, o que requer a feature time.
  • Date32 é mapeado de/para i32 ou um newtype baseado nele e representa um número de dias decorridos desde 1970-01-01. Além disso, time::Date é compatível usando serde::time::date32, o que requer a feature time.
  • DateTime é mapeado de/para u32 ou um newtype baseado nele e representa um número de segundos decorridos desde o Unix epoch. Além disso, time::OffsetDateTime tem suporte por meio de serde::time::datetime, o que requer a feature time.
  • DateTime64(_) é mapeado de/para i32 ou um newtype que o encapsula e representa o tempo decorrido desde a Unix epoch. Além disso, há suporte a time::OffsetDateTime usando serde::time::datetime64::*, o que requer a feature time.
  • Tuple(A, B, ...) é mapeado de/para (A, B, ...) ou para um newtype sobre ele.
  • Array(_) é mapeado de/para qualquer slice, por exemplo Vec<_>, &[_]. Tipos personalizados também têm suporte.
  • Map(K, V) se comporta como Array((K, V)).
  • LowCardinality(_) tem suporte transparente.
  • Nullable(_) é mapeado de/para Option<_>. Para os helpers clickhouse::serde::*, adicione ::option.
  • Nested é compatível ao fornecer múltiplos arrays com renomeação.
  • Há suporte a tipos Geo. Point se comporta como uma tupla (f64, f64), e os demais tipos são apenas slices de pontos.
  • Os tipos de dados Variant, Dynamic e JSON (novo) ainda não são compatíveis.

Simulação

O crate fornece utilitários para simular o servidor CH e testar consultas DDL, SELECT, INSERT e WATCH. Esse recurso pode ser habilitado com a feature test-util. Use-o apenas como dev-dependency. Veja o exemplo.

Solução de problemas

CANNOT_READ_ALL_DATA

A causa mais comum do erro CANNOT_READ_ALL_DATA é que a definição da linha no lado da aplicação não corresponde à do ClickHouse. Considere a tabela a seguir:
Então, se EventLog estiver definido na aplicação com tipos incompatíveis, por exemplo:
Ao inserir os dados, pode ocorrer o seguinte erro:
Neste exemplo, isso é corrigido com a definição correta da struct EventLog:

Limitações conhecidas

  • Os tipos de dados Variant, Dynamic e JSON (novos) ainda não são suportados.
  • A vinculação de parâmetros no servidor ainda não é suportada; consulte esta issue para acompanhar.

Fale conosco

Se tiver alguma dúvida ou precisar de ajuda, fique à vontade para entrar em contato conosco pelo Slack da comunidade ou pelas issues do GitHub.
Última modificação em 23 de julho de 2026