Status experimental
As interfaces principais do cliente, da fonte de dados, da sessão e das operações, bem como as extensões de injeção de dependência, geram o aviso do compiladorCHTCP0001. Para indicar que você está ciente desse aviso durante a avaliação da API, adicione-o
a NoWarn no arquivo do projeto:
Versões do .NET compatíveis
O cliente TCP nativo é compatível com as seguintes versões do .NET:- .NET 8.0
- .NET 9.0
- .NET 10.0
Versões compatíveis do ClickHouse
O cliente TCP oferece suporte oficial às duas versões LTS mais recentes e aos três lançamentos mais recentes do servidor ClickHouse.Instalação
O cliente TCP nativo está incluído no pacoteClickHouse.Driver. Instale-o pelo NuGet:
Início rápido
Migração do cliente HTTP
A API TCP é independente deIClickHouseClient; não é uma opção de transporte para
ClickHouseClient nem para ClickHouseConnection. A maior parte do código SQL pode ser reutilizada, mas é necessário criar um
ClickHouseTcpClient e migrar cada operação para seu equivalente em TCP.
Métodos equivalentes
Por exemplo, um loop de leitura com o cliente HTTP:
Opções e parâmetros
As classes HTTPQueryOptions e ClickHouseParameterCollection não são intercambiáveis com suas equivalentes TCP.
Transfira os valores para ClickHouseTcpQueryOptions, onde as configurações são strings e
os parâmetros fazem parte do objeto de opções:
{name:Type} nativos do ClickHouse, mas não reescreve
placeholders @name no estilo ADO.NET. Ele também não permite definir, por consulta, banco de dados, função, bearer token, cabeçalho personalizado,
resolvedor ou formatador de parâmetros nem conversor de leitura. Consulte as limitações para saber quais
recursos continuam disponíveis apenas via HTTP.
Ciclo de vida da conexão e dos resultados
Ambos os clientes de alto nível são thread-safe e devem ser reutilizados. O cliente TCP mantém conexões nativas persistentes, em vez de conexões HTTP, implementaIAsyncDisposable e normalmente deve ser
descartado de forma assíncrona quando a aplicação é encerrada.
As linhas de QueryAsync pertencem a quem faz a chamada. Os blocos de StreamAsync e suas colunas são emprestados e válidos
apenas durante a iteração atual; copie os valores que precisarão continuar disponíveis depois dela. Sempre conclua ou descarte a
enumeração para que a conexão retorne ao pool. Use OpenSessionAsync quando várias operações
precisarem ser executadas na mesma conexão e preservar o estado da sessão.
Consulte o exemplo completo de
migração de HTTP para TCP
para ver os dois clientes em uso com a mesma tabela.
Configuração
Há duas maneiras de configurar um cliente TCP nativo:- String de conexão: Pares de chave/valor separados por ponto e vírgula que especificam o endpoint do servidor, as credenciais de autenticação e outras opções de conexão.
- Objeto
ClickHouseTcpClientOptions: Um objeto de configuração imutável e fortemente tipado definido no código.
ClickHouseTcpClient. Use
ClickHouseTcpConnectionStringBuilder para interpretar ou criar uma string de conexão e convertê-la em
ClickHouseTcpClientOptions.
Configurações de conexão
Os valores das propriedadesTimeSpan na string de conexão são expressos em segundos.
Formato de dados e serialização
Pool de conexões
Cada conexão executa uma operação por vez. O pool permite executar operações simultaneamente e reutilizar as conexões entre elas.Segurança
O protocolo nativo seguro usa um endpoint separado no servidor, não uma atualização da conexão existente. Um cliente TLS
deve se conectar a uma porta segura do protocolo nativo; ele não passa a usar uma conexão sem criptografia.
ConfigureTls é
aplicado por último e pode substituir a validação do certificado e do nome do host. Por isso, revise com cuidado os callbacks
personalizados.
Logging e depuração
O logger do cliente registra eventos do ciclo de vida e das operações no lado do cliente. Já os pacotes de log do servidor são enviados
para
ClickHouseTcpQueryCallbacks.OnLog. Como o texto da instrução pode conter dados confidenciais, ele é
excluído das tags de atividade por padrão e bastante truncado nos logs de depuração.
Configurações personalizadas
ClickHouseTcpClientOptions.CustomSettings aplica as configurações do servidor ClickHouse a todas as consultas e
inserções. Em cada operação, os valores de ClickHouseTcpQueryOptions.Settings substituem os valores de
nível do cliente que tenham o mesmo nome.
set_ a cada configuração do servidor:
set_ ao adicionar uma configuração a CustomSettings ou às Settings
de cada operação.
ClickHouseTcpQueryOptions
ClickHouseTcpQueryOptions permite definir configurações para cada operação. Todas as propriedades são opcionais.
ClickHouseTcpInsertOptions
ClickHouseTcpInsertOptions estende ClickHouseTcpQueryOptions com configurações para inserts nativos
em blocos. Todas as propriedades das opções de consulta também estão disponíveis.
ClickHouseTcpClient
ClickHouseTcpClient é a API de alto nível para o protocolo TCP nativo. Executa instruções e
consultas escalares, transmite resultados como blocos colunares, linhas ou POCOs, insere dados colunares ou organizados em linhas
e abre sessões vinculadas a uma conexão.
O cliente é thread-safe e mantém um pool de conexões. Crie um cliente por endpoint, compartilhe-o
por toda a aplicação e libere seus recursos ao encerrá-la. As operações são executadas em paralelo até o limite de
MaxPoolSize; as demais aguardam uma conexão por até PoolTimeout.
Criando um cliente
Crie um cliente usando uma string de conexão ouClickHouseTcpClientOptions. Consulte
Configuração para conhecer as configurações disponíveis.
Usando uma string de conexão:
PoolTimeout antes de serem abortadas.
Injeção de dependência
AddClickHouseTcpDataSource registra uma única instância de fonte de dados e disponibiliza o cliente dessa instância como
IClickHouseTcpClient e IClickHouseTcpOperations:
LoggerFactory,
o registro usará o ILoggerFactory do contêiner. Uma serviceKey pode registrar várias
fontes de dados independentes.
Executando consultas
UseExecuteAsync para instruções que não retornam linhas, como instruções DDL e mutações:
ExecuteAsync as lê e descarta. Para
INSERT INTO ... VALUES, use InsertAsync ou InsertRowsAsync e encerre a instrução SQL em
VALUES, sem incluir valores diretamente na instrução.
Leitura de dados
Escolha a API de leitura conforme a estrutura dos dados de que a aplicação precisa:Leituras escalares
ExecuteScalarAsync retorna a primeira coluna da primeira linha como um object:
NULL quanto uma consulta
que não retorna nenhuma linha produzem null.
Leitura de linhas
QueryAsync fornece cada linha como um object[] independente, com os valores na ordem das colunas do resultado:
Leitura de POCOs
QueryAsync<T> mapeia as colunas para propriedades públicas que podem ser alteradas. A correspondência entre os nomes ignora diferenças entre maiúsculas e minúsculas e
caracteres de sublinhado; use ClickHouseTcpColumn para definir um nome explícito e ClickHouseTcpNotMapped para
excluir uma propriedade.
Leituras de blocos colunares
StreamAsync disponibiliza o resultado no formato colunar nativo como uma sequência de valores Block. Essa é a forma mais rápida de ler os dados.
Sempre conclua a enumeração ou descarte o enumerador para que a conexão retorne ao pool.
Block.Column<T> acessa o tipo CLR produzido pelo decodificador. Use Block.ReadAs<T> ou uma
interface especializada, como IDateTimeColumn, quando precisar converter os valores.
Inserção de dados
As inserções nativas enviam dados em blocos colunares no formato wire. O SQL deve ser uma instruçãoINSERT INTO ... VALUES
sem uma lista de valores na própria instrução. Use colunas tipadas para minimizar o processamento no lado do cliente ou as sobrecargas para linhas e
objetos POCO quando a aplicação já tiver dados organizados em linhas.
Inserções colunares
InsertAsync aceita dados já organizados em colunas com tipos definidos. Essa é a maneira mais rápida de inserir dados.
InsertAsync, desde que a
inserção seja concluída antes que esse bloco seja liberado.
Inserção de linhas
InsertRowsAsync aceita linhas do tipo object[]. Os valores são associados às colunas da lista SQL conforme a posição:
Variant ou Dynamic. Não modifique as linhas até que a operação seja concluída.
Inserção com POCO
A sobrecarga genéricaInsertRowsAsync<T> mapeia as colunas de destino para propriedades públicas de leitura,
seguindo as mesmas regras de nomenclatura e atributos usadas nas leituras com POCO:
ClickHouseTcpNotMapped exclui do mapeamento propriedades usadas apenas pela aplicação, como
ImportBatch.
Parâmetros SQL
O cliente nativo vincula valores aos marcadores de posição{name:Type} do ClickHouse. Ele não reescreve
marcadores de posição @name no estilo ADO.NET.
ClickHouseTcpParameter.ClickHouseType. Use o tipo Identifier para nomes de tabelas e colunas.
Quando um DateTime ou DateTimeOffset representar um instante específico, informe um fuso horário, como
{timestamp:DateTime('UTC')}; caso contrário, o fuso horário da sessão do servidor poderá alterar sua interpretação.
ID da consulta
Toda operação tem um ID de consulta usado pelas tabelas de sistema do ClickHouse, pelos logs do cliente e pelos spans de rastreamento. QuandoQueryId é nulo ou vazio, o cliente gera um novo GUID. Defina esse ID quando for necessário
correlacionar a operação com um identificador da aplicação:
Progresso e metadados da consulta
ConfigureClickHouseTcpQueryOptions.Callbacks para receber metadados intercalados com a resposta:
OnLog, OnProfileEvents, OnTotals e OnExtremes são emprestados e não devem ser usados após o retorno do
callback.
O ClickHouse não envia pacotes de progresso da consulta para linhas enviadas em uma inserção. Use
OnBlockWritten para acompanhar os blocos enviados pelo cliente; ele informa o progresso da transmissão, mas não indica que o
servidor confirmou a inserção.
Cancelamento
Todas as operações aceitam umCancellationToken:
Informações do servidor e verificações de saúde
GetServerInfoAsync retorna a identidade, a versão, o fuso horário e as informações do protocolo negociado do servidor
obtidas durante o handshake do protocolo nativo:
ProtocolRevision, a revisão negociada entre o cliente e o
servidor. Condicione os recursos SQL, como tipos de dados e funções, a Version. O método reutiliza uma
conexão quando há uma disponível e abre outra quando o pool está vazio.
Use PingAsync para verificar se o serviço está pronto para receber tráfego pelo protocolo nativo:
Mais exemplos
Para ver exemplos completos e prontos para execução sobre leituras, inserções, tipos, sessões, TLS, observabilidade e tratamento de erros, consulte os exemplos de TCP nativo no repositório do GitHub.Sessões
As operações comuns do cliente utilizam qualquer conexão disponível no pool. Por isso, o estado local da conexão não fica isolado nem tem garantia de persistir entre chamadas. As conexões do pool podem se conectar a servidores diferentes. Abra uma sessão quando tabelas temporárias, instruçõesSET ou outra sequência de operações precisarem usar a mesma conexão.
IClickHouseTcpSession oferece as mesmas APIs de consulta, execução, inserção, ping e informações do servidor
que o cliente. A sessão não é segura para acesso por múltiplas threads. Suas operações são sequenciais: não é permitido iniciar outra operação antes que a atual
termine. Um resultado em streaming mantém a sessão ocupada até ser totalmente percorrido ou até que seu
enumerador seja descartado.
Cada sessão ocupa um slot de MaxPoolSize durante todo o seu ciclo de vida. O cliente pode continuar usando outras
conexões do pool, mas, quando há apenas uma conexão no pool, as demais operações do cliente aguardam
até que a sessão seja descartada ou PoolTimeout expire.
Descarte a sessão antes de descartar o cliente que a criou. Ao descartar a sessão, a
conexão dedicada é fechada em vez de devolvida ao pool, impedindo que chamadas posteriores herdem suas
tabelas temporárias ou configurações. Uma falha na conexão ou no protocolo, um cancelamento ou um fluxo de
resultados incompleto pode tornar a sessão inutilizável; quando IsOpen passar a ser false, abra uma nova sessão.
Boas práticas
Ciclo de vida do cliente e pooling
Crie umClickHouseTcpClient ou ClickHouseTcpDataSource para cada combinação de endpoint e
configuração e reutilize-o durante todo o ciclo de vida da aplicação. O cliente é thread-safe e mantém
seu próprio pool de conexões; criar um cliente por operação gera um novo pool a cada vez e impede a reutilização das
conexões.
Em uma aplicação com injeção de dependências, registre AddClickHouseTcpDataSource uma única vez e injete
IClickHouseTcpClient. O provedor de serviços é responsável pelo ciclo de vida do cliente, portanto os componentes que o utilizam não devem descartar a
instância injetada. Fora da injeção de dependências, descarte o cliente ao encerrar a aplicação com await using.
Cada conexão nativa executa uma operação por vez. Portanto, MaxPoolSize limita tanto o número de conexões
abertas quanto o de operações simultâneas; as demais chamadas aguardam uma vaga por até PoolTimeout.
Escolha um valor que atenda à demanda real por operações simultâneas da aplicação sem exceder os limites de conexões e
consultas do lado do servidor. Aumentar esse valor não acelera uma consulta individual.
Considere estas situações em que o pool é utilizado:
- Um resultado em streaming mantém sua conexão até que seu enumerador seja descartado.
- Uma sessão mantém uma conexão durante todo o seu ciclo de vida e aceita uma operação por vez.
- Se um resultado for abandonado, uma operação em andamento for cancelada ou ocorrer uma falha de protocolo ou conexão, a conexão será fechada em vez de reutilizada.
ClickHouse.Driver.Tcp.Pool para diagnosticar o esgotamento do pool,
o fechamento inesperado de conexões ou reconexões frequentes.
Tempos limite e cancelamento
O cliente TCP tem limites distintos para cada tipo de espera:
Uma obtenção de conexão que primeiro espera por uma vaga no pool e depois abre uma nova conexão pode levar até
PoolTimeout + DialTimeout. ReadTimeout é reiniciado a cada leitura do transporte. Portanto, uma consulta longa que
continua enviando informações de progresso ou dados pode durar mais que esse valor. Configure-o com um valor alto o suficiente para períodos normais
sem resposta do servidor; use TimeSpan.Zero somente quando outro tempo limite restringir de forma confiável a
duração da operação.
Use um token de cancelamento quando precisar de um tempo limite para toda a operação:
Tratamento de data e hora
PrefiraDateTime('UTC') ou DateTime64(S, 'UTC') para timestamps e use DateTimeOffset ou um
DateTime cujo Kind seja Utc no código da aplicação. Isso deixa explícito o instante representado
e evita a dependência do fuso horário do servidor ou da sessão.
O cliente TCP aplica estas regras ao gravar valores DateTime:
Uma hora inexistente devido à transição para o horário de verão é rejeitada porque não corresponde a nenhum
instante. Se a hora for ambígua no retorno do horário de verão, é escolhida a primeira ocorrência. Use
DateTimeOffset quando a
escolha precisar ser explícita.
Para parâmetros SQL que representam um instante, inclua o fuso horário no marcador de posição:
DateTime e DateTime64 expõem, por padrão, suas contagens brutas como uint ou long.
Use Block.ReadAs<DateTimeOffset>, IDateTimeColumn.GetDateTimeOffset ou uma propriedade POCO correspondente
quando for mais conveniente trabalhar com uma data e hora. Mantenha a contagem bruta quando cada dígito importar:
DateTimeOffset tem resolução de 100 nanossegundos. Por isso, ler DateTime64 com escala 8 ou 9 por meio dele
faz perder a precisão das frações de tick.
Use DateOnly para Date e Date32. Use TimeSpan para valores de Time e Time64 que possam ser
negativos ou ultrapassar 24 horas; TimeOnly só é adequado quando a coluna está limitada a um
horário do dia.
Streaming e ciclo de vida dos resultados
UseStreamAsync e colunas tipadas para processar dados com alta vazão. Essa abordagem acompanha a organização
colunar do ClickHouse e evita arrays por linha, boxing e alocação de POCOs. Use QueryAsync<T> quando for mais
importante ter um modelo próprio da aplicação do que minimizar as alocações. Use a versão não tipada de
QueryAsync apenas quando o schema não for conhecido em tempo de compilação.
Os blocos retornados por StreamAsync são emprestados. O bloco, suas colunas, as colunas filhas de tipos compostos e
todos os spans são válidos apenas durante a iteração atual do laço. Processe os dados ali mesmo ou copie os valores que
precisam permanecer disponíveis após a iteração:
await foreach descarte o enumerador. Se você precisar de apenas parte do
resultado, use LIMIT no SQL e selecione somente as colunas necessárias. Interromper
a iteração antes do fim cancela o restante da resposta e impede a reutilização da conexão.
Formato da inserção e agrupamento em lote
PrefiraInsertAsync com colunas tipadas quando os dados já estiverem em formato colunar. Essa opção exige menos
conversões no cliente. InsertRowsAsync<T> é a escolha natural para dados POCO; linhas object[]
sem tipagem oferecem mais flexibilidade, mas alocam arrays e fazem o boxing de tipos de valor.
Envie uma quantidade significativa de linhas por chamada de inserção, em vez de fazer muitas inserções pequenas. Em cada
chamada, MaxRowsPerBlock divide os dados em blocos no formato wire nativo. O valor padrão de 50.000 linhas também
limita o tamanho dos buffers temporários de coluna usados na conversão de entradas em formato de linha e POCO. Aumentá-lo pode
melhorar a vazão para linhas com poucas colunas, mas aumenta o pico de uso de memória; defini-lo como null grava toda a
inserção em um único bloco e converte de uma só vez toda a entrada orientada a linhas desse bloco.
MaxSendBufferBytes limita, de forma independente, a quantidade de dados codificados mantidos no buffer antes de serem gravados
no socket. É um limite flexível verificado entre colunas, portanto uma única coluna larga pode ultrapassá-lo.
Entradas em formato de linha e POCO são convertidas um bloco por vez. Assim, um valor inválido em um bloco posterior pode ser
detectado depois que os blocos anteriores já tiverem sido enviados. Valide a possibilidade de valores nulos e os tipos CLR antes da
inserção quando a qualidade dos dados for incerta e defina um DeduplicationToken derivado dos dados sempre que o
lote lógico puder ser inserido novamente.
Tipos de dados compatíveis
As tabelas abaixo diferenciam o tipo retornado peloIColumn<T> decodificado dos tipos adicionais
disponíveis por meio da conversão com Block.ReadAs<T>, do mapeamento de POCO com QueryAsync<T> ou de inserções. Você pode consultar o mesmo
resolvedor usado por essas operações para verificar se um determinado mapeamento é compatível:
Nullable, Array, Tuple, Map e LowCardinality também se aplicam recursivamente aos seus
tipos internos.
Mapeamento de tipos: leitura a partir do ClickHouse
Default .NET type corresponde ao T exposto por Block.Column<T> e IColumn<T>. Os tipos listados na coluna
Also readable as podem ser lidos por meio de Block.ReadAs<T> e das propriedades de POCO.
Tipos inteiros
Tipos de ponto flutuante
Tipos decimais
ClickHouseTcpDecimal armazena uma mantissa representada por um inteiro de tamanho arbitrário e uma escala, preservando valores
cuja precisão excede a capacidade de representação de decimal.
Tipo booleano
Tipos de string
Use
IStringColumn.GetBytes(row) ou leia os dados como byte[] quando eles puderem não ser UTF-8 válido.
FixedString(N) preserva todos os N bytes, inclusive os bytes zero no final.
Tipos de data e hora
A representação como inteiro bruto é o padrão para que as leituras colunares preservem o valor wire exato. As
conversões de data e hora usam o fuso horário declarado no tipo ou, se não houver um, o fuso horário da sessão.
A leitura de
Time ou Time64 como TimeOnly lança uma exceção se o valor for negativo ou igual ou superior a
24 horas; use TimeSpan para abranger todo o intervalo do ClickHouse.
Tipos enum
IEnumColumn também expõe o mapeamento declarado entre rótulos e valores ordinais.
Outros tipos escalares
Tipos compostos
Tuplas podem conter até sete elementos. Uma coluna
Nested pode ter qualquer número de campos e deve ser lida
preferencialmente por meio de INestedColumn, que expõe as colunas planas dos campos nomeados e os offsets de linha
compartilhados sem alocar registros encapsulados em objetos. Com a configuração padrão flatten_nested = 1 do ClickHouse,
os campos aninhados chegam como colunas Array(T) separadas, cujos nomes contêm pontos.
Tipos Variant, Dynamic e JSON
Variant e Dynamic retornam o valor CLR do tipo selecionado em cada linha ou null. As
visões colunares desses tipos expõem o fluxo de discriminadores e uma coluna filha tipada para cada tipo em tempo de execução, evitando
o boxing no processamento de dados por coluna.
O cliente TCP lê JSON usando a serialização de String do ClickHouse. Por padrão, o cliente habilita
output_format_native_write_json_as_string = 1; se essa configuração for desabilitada, as leituras de JSON ficam
sem suporte. Como o ClickHouse interpreta e normaliza o JSON, o texto retornado pode diferir do texto inserido quanto à ordem das chaves,
aos espaços em branco e à formatação dos números.
Tipos geométricos
Geometry é representado por uma IVariantColumn que pode conter qualquer um dos seis tipos geométricos.
Tipo QBit
O cliente TCP oferece suporte à forma
QBit(T, N), com dois argumentos e sem stride. O layout
com três argumentos e stride não é compatível.
Tipos de AggregateFunction
Uma coluna
AggregateFunction contém um estado intermediário específico da função. Finalize-o no
servidor, por exemplo, com sumMerge(column), e leia o valor resultante.
Mapeamento de tipos: gravação no ClickHouse
Cada entrada representa o tipo CLR de uma linha daIColumn passada a InsertAsync. Esses mapeamentos são
exatos: o cliente TCP não realiza coerções de tipo como as de Convert.
Tipos inteiros
Tipos de ponto flutuante
Ao gravar um
BFloat16, cada valor float é truncado para a representação de ponto flutuante brain de 16 bits.
Tipos decimais
A gravação lança
OverflowException quando a mantissa ajustada à escala excede a precisão declarada.
Tipo booleano
Tipos de string
FixedString(N) não aceita string de propósito; codifique o valor e complete-o com bytes explicitamente para que
sua representação binária exata não deixe dúvidas.
Tipos de data e hora
Os valores inteiros brutos usam as unidades indicadas na tabela de leitura.
DateTimeOffset preserva o instante.
DateTime segue o valor de Kind; um valor Unspecified é interpretado como a hora local no
fuso horário da coluna ou, se a coluna não especificar um, no fuso horário da sessão.
Tipos enum
Um rótulo desconhecido é rejeitado antes do envio dos dados.
Outros tipos escalares
Tipos compostos
O formato aceito é recursivo:Array(Nullable(DateTime)) aceita um DateTime?[] para cada
linha, e Map(String, UInt32) aceita um KeyValuePair<string, uint>[].
As gravações diretas de
Nested usam o formato de colunas densas retornado por uma leitura anterior. Para inserções criadas pela aplicação,
mantenha a representação padrão flatten_nested = 1 e grave cada campo Array(T) cujo nome contém um ponto
em sua própria coluna.
Tipos Variant, Dynamic e JSON
Para
Variant, o tipo em tempo de execução deve corresponder ao tipo CLR padrão de uma única alternativa. Mapeamentos
de conveniência, como gravar um DateTime em uma alternativa DateTime, não são usados dentro de uma variante;
use o tipo bruto padrão da alternativa. Dynamic aceita valores escalares, além de
arrays, maps e tuplas com suporte recursivo.
Tipo geométrico
Em uma coluna
Geometry criada pela aplicação, apenas Point e MultiPolygon têm estruturas CLR exclusivas.
Ring e LineString têm a mesma estrutura, assim como Polygon e MultiLineString. Por isso, o cliente não consegue
inferir a qual dessas alternativas um valor object corresponde. Uma coluna Geometry decodificada preserva seus
discriminadores e pode ser inserida novamente sem essa ambiguidade.
Tipo QBit
Tipos de AggregateFunction
Compressão
Por padrão, o cliente habilita a compressão e usa LZ4 nos blocos que grava; o ClickHouse também usa LZ4 por padrão nos blocos de resposta. A compressão se aplica aos blocos de resultado e aos blocos enviados em uma inserção, enquanto o texto da consulta, as informações de progresso, as exceções e os demais pacotes do protocolo mantêm sua codificação wire normal. Use a chaveCompression da string de conexão para selecionar o codec usado pelo cliente:
IClickHouseCompressor:
Compressor = null para desativar a compressão. Um compressor personalizado deve ser compatível com o enquadramento nativo de blocos;
compressores que só oferecem suporte a corpos de requisições HTTP são rejeitados na criação do cliente.
Como selecionar o codec da resposta
Compressor determina como os blocos gravados pelo cliente são comprimidos. O pacote de consulta nativo solicita
compressão ao servidor, mas não especifica um codec. Por isso, o ClickHouse seleciona o codec da resposta de acordo com
a configuração network_compression_method. Por padrão, o servidor usa LZ4.
Quando necessário, defina o codec da resposta para cada operação:
Tratamento de erros
As falhas relatadas pelo ClickHouse ou pela conexão nativa derivam deClickHouseTcpException,
que, por sua vez, deriva de DbException:
ClickHouseTcpServerException expõe RawCode, o código numérico exato enviado pelo servidor,
e Code, o ClickHouseErrorCode correspondente, quando identificado pelo driver. Ela também contém o
Name da exceção do servidor, ServerStackTrace e eventuais exceções aninhadas do servidor em
InnerException.
ClickHouseErrorCode têm Code == ClickHouseErrorCode.Unknown; consulte
RawCode sem presumir que o enum inclua todos os erros do ClickHouse.
Os erros de validação de argumentos e de ciclo de vida de objetos mantêm seus tipos habituais de exceção do .NET.
O cancelamento gera OperationCanceledException. DialTimeout e ReadTimeout geram
ClickHouseTcpConnectionException com uma TimeoutException como exceção interna, e a conexão é descartada.
PoolTimeout gera uma TimeoutException simples, que não é uma ClickHouseTcpException: nenhuma conexão
falhou. Para resolver o problema, reduza o número de operações simultâneas, aumente o pool ou conclua a enumeração dos resultados.
Como tentar operações novamente
Se ocorrer uma falha de conexão ou o tempo limite for excedido durante uma inserção, não será possível saber se ela foi concluída: o servidor pode ter confirmado as linhas antes que o cliente recebesse a resposta. Defina umDeduplicationToken estável para o lote lógico antes de tentar novamente:
Logging e diagnóstico
O cliente TCP se integra aoMicrosoft.Extensions.Logging. O logging é opcional; na ausência de uma
LoggerFactory, o cliente não cria loggers nem formata mensagens de log.
ILoggerFactory do contêiner, a menos que as opções fornecidas já especifiquem um.
Categorias de logging
Configure as categorias usando a configuração padrão de logging do .NET:
Debug e inclui, no máximo, StatementMaxLength caracteres de
SQL. O valor padrão é cinco caracteres. Defina o valor como zero ou menos para omitir o texto da instrução dos logs,
ou aumente-o somente após considerar parâmetros e literais que possam conter dados sensíveis.
Mensagens de log do servidor
A integração de logging registra o comportamento do lado do cliente. Os pacotes do log de consultas do próprio ClickHouse são separados e enviados paraClickHouseTcpQueryCallbacks.OnLog. Habilite-os com a
configuração do servidor send_logs_level:
OpenTelemetry
O cliente TCP emite spans de rastreamento distribuído por meio da APISystem.Diagnostics.Activity do .NET.
Inscreva um provedor de rastreamento do OpenTelemetry na fonte de atividades TCP:
ClickHouse.Driver.Tcp, diferente da fonte de dados do cliente HTTP. Assim,
é possível coletar dados de cada transporte de forma independente. Quando não há nenhum listener inscrito, as operações não
geram atividades.
Spans e atributos
O cliente emite spans para operações SQL, verificações de conectividade e novas conexões. Um span SQL recebe o nome da palavra-chave que inicia a instrução, comoSELECT ou INSERT; se não houver uma palavra-chave inicial reconhecível, o span recebe o nome query. Um span connect abrange a conexão via socket, a negociação TLS e o handshake nativo. Os spans de instruções também incluem o tempo de espera por uma conexão do pool.
Os contadores só aparecem quando o servidor ou o cliente tem um valor relevante a informar. Por exemplo, uma inserção que envia blocos informa o número de linhas enviadas pelo cliente, mas não recebe contadores de leitura do servidor. Spans de operações que falharam também contêm um evento
exception com o tipo da exceção, a mensagem e o rastreamento de pilha.
Texto SQL e dados sensíveis
Por padrão, o texto SQL não é incluído nos spans. Ative sua inclusão explicitamente e defina um limite adequado:StatementMaxLength limita o tamanho do atributo db.query.text e do SQL nos logs de depuração. Um valor igual ou inferior a zero
faz com que o texto SQL seja omitido de ambos. Revise também as mensagens de exceção e os rastreamentos de pilha exportados, pois
os erros do servidor podem conter detalhes da consulta.
Propagação do contexto de rastreamento
QuandoActivity.Current usa o formato de ID W3C, o cliente inclui o ID do rastreamento, o ID do span, os sinalizadores
e o estado do rastreamento no pacote nativo de consulta. Assim, o ClickHouse pode criar spans do servidor no mesmo
rastreamento distribuído. A coleta e a amostragem de spans do lado do servidor continuam a depender da configuração do ClickHouse; por
exemplo, é possível definir a probabilidade de amostragem por consulta:
system.query_log e, se configurado, com system.opentelemetry_span_log do ClickHouse.
Limitações
O cliente TCP é experimental e não oferece todos os recursos do cliente HTTP.Funcionalidades disponíveis apenas via HTTP
A API TCP não é um provedor ADO.NET e não pode ser usada com ORMs. Ela também não oferece suporte a entrada e saída em CSV, JSONEachRow, Parquet ou fluxo bruto; autenticação bearer ou cabeçalhos HTTP personalizados; resolução personalizada de tipos de parâmetros, formatação ou conversão na leitura; nem à definição de um banco de dados ou uma função para cada consulta. Use o cliente HTTP quando uma aplicação precisar de alguma dessas funcionalidades.Parâmetros SQL
Apenas os placeholders{name:Type} nativos do ClickHouse são aceitos; o cliente TCP não reescreve
placeholders @name no estilo do ADO.NET. Nas versões 25.8 a 26.6 do ClickHouse, nomes de parâmetros que coincidem com
configurações do servidor, como limit ou offset, podem ser interpretados como configurações e rejeitados. Ao oferecer suporte a essas versões,
renomeie os parâmetros, por exemplo, para row_limit.
Cobertura de tipos de dados
A seção tipos de dados compatíveis apresenta todos os mapeamentos. O codec nativo atual tem as seguintes limitações:- As tuplas podem conter, no máximo, sete elementos.
- Estados intermediários de
AggregateFunction(function, ...)não são compatíveis. Finalize-os no servidor, por exemplo, comsumMerge(column), e leia o resultado. - Apenas o layout
QBit(T, N)com dois argumentos e sem stride é compatível. JSONusa a serialização String do ClickHouse e exigeoutput_format_native_write_json_as_string = 1, que o cliente solicita por padrão.- Inserções criadas pela aplicação não têm representação orientada a linhas para
Nested(...)quandoflatten_nested = 0. Em vez disso, use as colunasArray(T)achatadas, com nomes separados por pontos, que são o padrão. - Uma coluna
Geometrycriada pela aplicação não permite distinguir alternativas que compartilham a mesma estrutura CLR, comoRingeLineString. Insira o tipo geométrico específico ou reinsira uma colunaGeometrydecodificada que preserve seus discriminadores.
Novas tentativas automáticas
O cliente não repete automaticamente as operações que falharam. Tente novamente apenas as operações que podem ser repetidas com segurança e defina umDeduplicationToken fixo antes de tentar novamente uma inserção cujo resultado é desconhecido.
Consulte como tentar operações novamente para saber mais.