Visão geral
- Usa
serdepara serializar/desserializar linhas. - Oferece suporte a atributos do
serde:skip_serializing,skip_deserializing,rename. - Usa o formato
RowBinaryvia transporte HTTP.- Há planos de migrar para
Nativevia TCP.
- Há planos de migrar para
- Oferece suporte a TLS (por meio dos recursos
native-tlserustls-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
Cargo.toml:
Features do Cargo
lz4(habilitado por padrão) — habilita as variantesCompression::Lz4eCompression::Lz4Hc(_). Quando habilitado,Compression::Lz4é usado por padrão em todas as consultas, exceto emWATCH.native-tls— oferece suporte a URLs com o esquemaHTTPSviahyper-tls, que faz link com o OpenSSL.rustls-tls— oferece suporte a URLs com o esquemaHTTPSviahyper-rustls, que não faz link com o OpenSSL.inserter— habilitaclient.inserter().test-util— adiciona mocks. Veja o exemplo. Use-o apenas emdev-dependencies.watch— habilita a funcionalidadeclient.watch. Consulte a seção correspondente para mais detalhes.uuid— adicionaserde::uuidpara trabalhar com a crate uuid.time— adicionaserde::timepara trabalhar com a crate time.
Compatibilidade entre versões do ClickHouse
wa-37420 para resolver esse problema. Observação: essa feature não deve ser usada com versões mais recentes do ClickHouse.
Exemplos
Uso
O
crate ch2rs é útil para gerar um tipo de linha com base no ClickHouse.Criando uma instância de cliente
Conexão HTTPS ou ClickHouse Cloud
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:
- Exemplo de HTTPS com ClickHouse Cloud no repositório do client. Isso também deve se aplicar a conexões HTTPS em ambientes on-premise.
Selecionando linhas
- O placeholder
?fieldsé substituído porno, name(campos deRow). - O placeholder
?é substituído pelos valores nas chamadasbind()a seguir. - Os métodos convenientes
fetch_one::<Row>()efetch_all::<Row>()podem ser usados para obter a primeira linha ou todas as linhas, respectivamente. sql::Identifierpode ser usado para vincular nomes de tabelas.
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.
Inserindo linhas
- Se
end()não for chamado, oINSERTé 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)
async_insert ao método insert (ou até mesmo à própria instância Client, para que isso afete todas as chamadas de insert).
- Exemplo de async insert no repositório do cliente.
Funcionalidade Inserter (batching no lado do cliente)
inserter do Cargo.
Inserterencerra a inserção ativa emcommit()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 comwith_period_biaspara evitar picos de carga causados por insertores paralelos. Inserter::time_left()pode ser usado para detectar quando o período atual termina. ChameInserter::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 setest-utilestiver habilitado (assim, o tempo pode ser controlado portokio::time::advance()em testes personalizados). - Todas as linhas entre chamadas de
commit()são inseridas na mesma instruçãoINSERT.
Executando DDLs
wait_end_of_query. Isso pode ser feito assim:
Configurações do ClickHouse
with_option. Por exemplo:
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
.with_option, você pode definir a opção query_id para identificar consultas no log de consultas do ClickHouse.
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.ID da sessão
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.
Cabeçalhos HTTP personalizados
Cliente HTTP personalizado
Tipos de dados
Veja também os exemplos adicionais:
(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)Int256não tem suporte direto, mas há uma solução alternativa.Float(32|64)tem mapeamento de/para os correspondentesf(32|64)ou newtypes baseados neles.Decimal(32|64|128)tem mapeamento de/para os correspondentesi(32|64|128)ou newtypes baseados neles. É mais prático usarfixnumou outra implementação de números de ponto fixo com sinal.Booleantem mapeamento de/paraboolou newtypes baseados nele.Stringtem mapeamento de/para qualquer tipo de string ou bytes, por exemplo,&str,&[u8],String,Vec<u8>ouSmartString. Novos tipos também têm suporte. Para armazenar bytes, considere usarserde_bytes, pois é mais eficiente.
FixedString(N)é suportado como um array de bytes, por exemplo[u8; N].
Enum(8|16)têm suporte viaserde_repr.
UUIDé mapeado entreuuid::Uuidcom o uso deserde::uuid. Requer a featureuuid.
IPv6é mapeado para/destd::net::Ipv6Addr.IPv4é mapeado para/destd::net::Ipv4Addrusandoserde::ipv4.
Dateé mapeado de/parau16ou um newtype baseado nele e representa um número de dias decorridos desde1970-01-01. Além disso,time::Datetambém é compatível usandoserde::time::date, o que requer a featuretime.
Date32é mapeado de/parai32ou um newtype baseado nele e representa um número de dias decorridos desde1970-01-01. Além disso,time::Dateé compatível usandoserde::time::date32, o que requer a featuretime.
DateTimeé mapeado de/parau32ou um newtype baseado nele e representa um número de segundos decorridos desde o Unix epoch. Além disso,time::OffsetDateTimetem suporte por meio deserde::time::datetime, o que requer a featuretime.
DateTime64(_)é mapeado de/parai32ou umnewtypeque o encapsula e representa o tempo decorrido desde a Unix epoch. Além disso, há suporte atime::OffsetDateTimeusandoserde::time::datetime64::*, o que requer a featuretime.
Tuple(A, B, ...)é mapeado de/para(A, B, ...)ou para um newtype sobre ele.Array(_)é mapeado de/para qualquer slice, por exemploVec<_>,&[_]. Tipos personalizados também têm suporte.Map(K, V)se comporta comoArray((K, V)).LowCardinality(_)tem suporte transparente.Nullable(_)é mapeado de/paraOption<_>. Para os helpersclickhouse::serde::*, adicione::option.
Nestedé compatível ao fornecer múltiplos arrays com renomeação.
- Há suporte a tipos
Geo.Pointse comporta como uma tupla(f64, f64), e os demais tipos são apenas slices de pontos.
- Os tipos de dados
Variant,DynamiceJSON(novo) ainda não são compatíveis.
Simulação
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
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:
EventLog estiver definido na aplicação com tipos incompatíveis, por exemplo:
EventLog:
Limitações conhecidas
- Os tipos de dados
Variant,DynamiceJSON(novos) ainda não são suportados. - A vinculação de parâmetros no servidor ainda não é suportada; consulte esta issue para acompanhar.