Pular para o conteúdo principal
O cliente oficial em Rust para conexão com o ClickHouse, desenvolvido originalmente por Paul Loyd. O código-fonte do cliente está disponível no repositório no GitHub.

Visão geral

  • Usa serde para codificar/decodificar linhas.
  • Suporta atributos do serde: skip_serializing, skip_deserializing, rename.
  • Usa o formato RowBinary no transporte HTTP.
    • Há planos para migrar para Native sobre TCP.
  • Suporta TLS (por meio das features native-tls e rustls-tls).
  • Suporta compressão e descompressão (LZ4).
  • Fornece APIs para selecionar ou inserir dados, executar DDLs e fazer batching no cliente.
  • Fornece mocks úteis para testes unitários.

Instalação

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

Recursos do Cargo

  • lz4 (ativado por padrão) — habilita as variantes Compression::Lz4 e Compression::Lz4Hc(_). Quando ativado, Compression::Lz4 é usado por padrão em todas as queries, exceto para WATCH.
  • native-tls — oferece suporte a URLs com o schema HTTPS via hyper-tls, que faz link com o OpenSSL.
  • rustls-tls — oferece suporte a URLs com o schema 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 funcionar com a crate uuid.
  • time — adiciona serde::time para funcionar com a crate time.
Ao se conectar ao ClickHouse por meio de uma URL HTTPS, o recurso native-tls ou rustls-tls deve estar habilitado. Se ambos estiverem habilitados, o recurso 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 o recurso wa-37420 para resolver esse problema. Observação: esse recurso não deve ser usado com versões mais recentes do ClickHouse.

Exemplos

Nosso objetivo é abranger vários cenários de uso do cliente com os examples no repositório do cliente. A visão geral está disponível no README dos examples. Se algo não estiver claro ou estiver faltando nos examples ou na documentação a seguir, sinta-se à 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 reaproveitar o pool de conexões subjacente do hyper.

Conexão HTTPS ou ClickHouse Cloud

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

Selecionando linhas

  • O marcador ?fields é substituído por no, name (campos de Row).
  • O marcador ? é substituído pelos valores nas chamadas bind() a seguir.
  • Os métodos práticos 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 associar nomes de tabelas.
Observação: como toda a resposta é transmitida por 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 da 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 levar a um maior consumo de memória no servidor e provavelmente reduzirá o desempenho geral.

Inserção de linhas

  • Se end() não for chamado, o INSERT será abortado.
  • As linhas são enviadas progressivamente como um stream para distribuir a carga de rede.
  • O ClickHouse insere lotes de forma atômica somente se todas as linhas couberem na mesma partição e se a quantidade delas for menor que max_insert_block_size.

Async insert (batching no servidor)

Você pode usar as inserções assíncronas do ClickHouse para evitar o batching no 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:

Recurso Inserter (batching no cliente)

Requer o recurso inserter do Cargo.
  • Inserter encerra a inserção ativa em commit() se qualquer um dos limites (max_bytes, max_rows, period) for atingido.
  • O intervalo entre o encerramento de INSERTs ativos pode ser ajustado 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 stream emitir itens com pouca frequência.
  • Os limiares de tempo são implementados com 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

Em uma implantação de nó único, basta executar as DDLs assim:
No entanto, em implantações em cluster com 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 maneira semelhante nos 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, ele 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 escolha para isso.
Veja também: exemplo de query_id no repositório do cliente.

ID da sessão

Assim como em query_id, você pode definir session_id para executar as instruções na mesma sessã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 à ausência de “sticky sessions”, 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 cliente.

Cabeçalhos HTTP personalizados

Se você estiver usando autenticação de proxy ou precisar enviar cabeçalhos personalizados, pode fazer 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 está sujeito a mudanças no futuro.
Veja também: exemplo de cliente HTTP personalizado no repositório do cliente.

Tipos de dados

  • (U)Int(8|16|32|64|128) corresponde aos tipos (u|i)(8|16|32|64|128) equivalentes, ou a newtypes baseados neles.
  • (U)Int256 não tem suporte direto, mas há uma solução alternativa.
  • Float(32|64) corresponde aos tipos f(32|64) equivalentes, ou a newtypes baseados neles.
  • Decimal(32|64|128) corresponde aos tipos i(32|64|128) equivalentes, ou a newtypes baseados neles. É mais prático usar fixnum ou outra implementação de números com sinal em ponto fixo.
  • Boolean corresponde a bool ou a newtypes baseados nele.
  • String corresponde a qualquer tipo de string ou bytes, por exemplo, &str, &[u8], String, Vec<u8> ou SmartString. Newtypes também têm suporte. Para armazenar bytes, considere usar serde_bytes, pois é mais eficiente.
  • FixedString(N) tem suporte como um array de bytes, por exemplo [u8; N].
  • UUID é mapeado de e para uuid::Uuid usando serde::uuid. Requer o recurso 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 com o uso de serde::time::date, o que requer o recurso 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 também é compatível com o uso de serde::time::date32, o que requer o recurso time.
  • DateTime é convertido de/para u32 ou um newtype baseado nele e representa um número de segundos decorridos desde a epoch UNIX. Além disso, time::OffsetDateTime é compatível ao usar serde::time::datetime, o que requer o recurso time.
  • DateTime64(_) é mapeado de/para i32 ou um newtype baseado nele e representa o tempo decorrido desde a epoch UNIX. Além disso, time::OffsetDateTime também tem suporte usando serde::time::datetime64::*, o que exige a feature time.
  • Tuple(A, B, ...) é mapeado de/para (A, B, ...) ou um newtype sobre ele.
  • Array(_) é mapeado de/para qualquer slice, por exemplo Vec<_>, &[_]. newtypes também são compatíveis.
  • 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.
  • Há suporte a Nested ao fornecer vários arrays com renomeação.
  • Há suporte a tipos Geo. Point se comporta como uma tupla (f64, f64), e os demais tipos são apenas sequências de pontos.
  • Os tipos de dados Variant, Dynamic e o (novo) JSON ainda não têm suporte.

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 o recurso test-util. Use-a 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 seguinte tabela:
Então, se EventLog estiver definido no lado da aplicação com tipos incompatíveis, por exemplo:
Ao inserir os dados, pode ocorrer o seguinte erro:
Neste exemplo, isso é resolvido com a definição correta da estrutura EventLog:

Limitações conhecidas

  • Os tipos de dados Variant, Dynamic e JSON (novo) ainda não são suportados.
  • O binding de parâmetros no servidor ainda não é suportado; consulte esta issue para acompanhar.

Fale conosco

Se você tiver alguma dúvida ou precisar de ajuda, fique à vontade para falar conosco no Slack da comunidade ou pelas issues do GitHub.
Última modificação em 3 de julho de 2026