FORMAT Native gerenciado pelo cliente, que abrange query, query_np, query_df, suas variantes de streaming por block e por linha, e as inserções, incluindo insert_df. Os métodos Arrow usam FORMAT Arrow e não são afetados, assim como as consultas raw, as inserções raw e os formatos não Native.
O codec é experimental e de uso opcional. O codec Python continua sendo o padrão.
Instalação
O codec compilado é distribuído como um wheel separado, chamadoclickhouse-connect-core, que fornece o módulo de extensão _ch_core. Instale o codec junto com as integrações usadas pela sua aplicação:
query_np, query_df, suas variantes de streaming e query(..., use_numpy=True). Consultas NumPy não exigem Pandas. Adicione o extra async para usar o cliente assíncrono.
O PyArrow continua sendo necessário para os métodos Arrow e para o armazenamento Pandas com Arrow como backend. Instale o extra arrow para usar esses recursos:
mode.string_storage do Pandas. Quando o PyArrow está instalado, as strings usam a conversão Arrow existente, com validação UTF-8 completa, em qualquer um dos backends de armazenamento. Sem o PyArrow, o driver usa a conversão de objetos em Rust, e o armazenamento padrão do Pandas usa strings Python. Solicitar explicitamente o armazenamento de strings Arrow sem o PyArrow gera um erro de dependência. UTF-8 inválido mantém a renderização hexadecimal existente em qualquer um dos backends de armazenamento.
O codec, seu empacotamento e seu conjunto de dependências são experimentais. A conversão direta de buffers agora trata colunas de inteiros não anuláveis de 8 a 64 bits, Float32/64, Boolean, BFloat16, Interval, Date, Date32, DateTime e DateTime64. Colunas escalares Time e Time64, incluindo valores anuláveis, também usam buffers diretos, assim como BFloat16 anulável e a saída estendida do Pandas para inteiros, floats e Interval anuláveis. BFloat16 mantém a saída float32 e sua política atual de valores ausentes Float32 do Pandas. Valores Interval continuam sendo contagens com sinal em sua unidade declarada. A conversão temporal mantém as unidades declaradas e as regras de fuso horário existentes. Aliases SimpleAggregateFunction anuláveis de Time64 agora retornam durações corretas e NaT para valores NULL. Colunas escalares anuláveis DateTime64(9) também usam buffers para preservar nanossegundos na saída do NumPy e do Pandas. As demais datas e timestamps anuláveis mantêm seus caminhos de conversão de objetos.
Arrays de Time/Time64, incluindo arrays aninhados e folhas anuláveis, e LowCardinality(Time), incluindo valores anuláveis, também usam buffers diretos. O aninhamento, as unidades de duração e as representações de nulos permanecem inalterados. LowCardinality(Time64) continua sem suporte no núcleo em Rust.
Para DateTime64(9) escalar anulável, query_df e query_df_stream preservam todos os nove dígitos fracionários, inclusive por meio de aliases SimpleAggregateFunction. No Pandas 3, colunas datetime na saída padrão agora usam unidades de nanossegundos em vez de microssegundos. A inferência atual de dtype object para blocos totalmente NULL permanece inalterada. Se um fuso horário nomeado colocar um valor fora do intervalo de nanossegundos do Pandas, essa coluna mantém a conversão de objetos e o comportamento de intervalo anteriores.
Para essas colunas, os campos de objeto de query_np e query_np_stream agora contêm células numpy.datetime64 em vez de células datetime do Python, com None para NULL do SQL. Valores com fuso nomeado usam ticks UTC sem metadados de fuso horário, assim como o codec Python. Isso preserva os nanossegundos sem exigir o Pandas. Use query_df se precisar de timestamps com fuso horário. Os demais tipos de células temporais anuláveis do NumPy permanecem inalterados.
Consultas NumPy e Pandas de DateTime64 escalar rejeitam precisões diferentes de 0, 3, 6 e 9 com ProgrammingError, inclusive em colunas anuláveis e aliases SimpleAggregateFunction.
Se um codec Rust for selecionado e o módulo compilado não estiver instalado, a criação do cliente gera um NotSupportedError que informa este comando de instalação.
Habilitando o codec
Selecione o codec com a opção de clientenative_codec:
O padrão também pode ser definido pela configuração comum
native_codec ou pela variável de ambiente CLICKHOUSE_CONNECT_NATIVE_CODEC. A precedência é: primeiro o keyword argument do cliente, depois a configuração comum e, por fim, a variável de ambiente.
A opção é ignorada para clientes com interface="chdb", que sempre usam o codec Python.
Quando usar o codec Rust
O codec Rust é mais útil para resultados grandes de DataFrame com tipos de texto, contêineres e tipos complexos comoString, LowCardinality, Map, Array, JSON, Decimal e UUID. Ele também pode ajudar em streams de blocos grandes de linhas e colunas, cargas de trabalho com consultas concorrentes e inserts em massa.
Resultados pequenos e consultas limitadas pela rede podem apresentar pouca diferença. Resultados numéricos simples já utilizam caminhos em massa eficientes no codec Python, portanto também tendem a se beneficiar menos.
Buffers diretos evitam arrays intermediários do Arrow para os tipos compatíveis. A montagem final dos resultados em NumPy e Pandas ainda pode alocar e copiar dados, portanto isso não torna todo resultado de consulta zero-copy.
Sem o PyArrow, a conversão de strings no Rust cria objetos string do Python a partir de cada bloco decodificado. Com os tamanhos de bloco padrão, o pico de memória para resultados grandes de String é próximo ao do codec Python. Blocos muito grandes, como um único bloco com um milhão de linhas, mantêm todo o bloco decodificado em memória enquanto suas strings são criadas e podem consumir mais memória de pico do que o codec Python. Para resultados grandes com Pandas StringDtype, instale o extra arrow e use o armazenamento de strings do Arrow. O Pandas 3 seleciona o armazenamento Arrow por padrão quando o PyArrow está instalado. O Pandas 2 requer pd.options.mode.string_storage = "pyarrow".
Chamadas query() com buffer sobre resultados muito largos ou totalmente numéricos podem, atualmente, ser mais lentas e consumir mais memória de pico com o codec Rust. Para essas cargas de trabalho, prefira query_df, query_row_block_stream ou query_column_block_stream. Para NumPy e Pandas, query_np_stream e query_df_stream também podem reduzir o pico de memória. Processe e libere cada bloco em vez de acumular todo o stream. O uso de memória ainda depende do tamanho de cada bloco, portanto fazer streaming de um único bloco grande não traz o mesmo benefício.
Faça um benchmark da sua própria carga de trabalho antes de adotar o codec. Use native_codec="rust_strict" durante as medições para que uma opção sem suporte ou uma dependência ausente gere um erro, em vez de encaminhar silenciosamente a consulta para o Python.
Regras de fallback
As decisões de fallback são tomadas antes que qualquer byte seja lido ou enviado, portanto nunca ocorre troca de codec no meio do stream. Para queries, a escolha acontece antes de o response body ser consumido. Para inserções, o codificador Rust só é selecionado quando todos os tipos de coluna têm suporte; caso contrário, a inserção inteira é executada no codec Python. Quandonaive_datetime_insert="server" está ativo, o rust encaminha ao codec Python qualquer inserção que contenha uma coluna DateTime ou DateTime64, de modo que a timezone declarada da coluna ou a server timezone seja aplicada. Já o rust_strict rejeita essa combinação. O modo padrão naive_datetime_insert="local" continua usando o codificador Rust.
Queries de metadados internas do driver, incluindo as instruções de reflexão do dialect do SQLAlchemy, sempre usam o codec Python, de forma silenciosa, em todos os modos.
Payloads Native malformados detectados pelo codec Rust geram DataError.
Versioning
Oclickhouse-connect-core é versionado de forma independente do clickhouse-connect. O extra rust requer clickhouse-connect-core>=0.2.1,<0.3. Quando um codec Rust é selecionado, o driver verifica tanto a versão da API de binding quanto a capability de buffer de coluna. A wheel do core 0.2.0 publicada não tem a capability de buffer de coluna. Se a wheel instalada for incompatível, a criação do cliente gera um NotSupportedError tanto para rust quanto para rust_strict, com este comando de upgrade:
clickhouse-connect-core e podem ser obtidas com um upgrade para uma wheel do core compatível. Alterações na integração Rust do driver exigem um upgrade do clickhouse-connect.
Diferenças de comportamento conhecidas
O codec Rust busca paridade célula a célula com o codec Python. As seguintes diferenças são conhecidas.- Os resultados de
query_npequery_dfpara colunasVariantcontêm objetos Python simples em vez de valores escalares do numpy. Os valores são iguais, mas os tipos das células diferem. - Valores
Dynamicque contêmTime64são materializados comodatetime.timedeltanos resultados dequery_npequery_dfdo Rust. Nas escalas 0, 3, 6 e 9, os valores são iguais às célulasnumpy.timedelta64do codec Python, mas os tipos das células diferem. Nas demais escalas, o codec Rust retornadatetime.timedelta, enquanto o codec Python geraProgrammingError, pois o NumPy não possui uma unidade correspondente. Os metadados dos membros deDynamicnão são expostos ao driver após a decodificação em Rust; portanto, usenative_codec="python"quando forem necessários os tipos de célula do NumPy ou a validação de escalas sem suporte. - Em
query_df, o codec Python pode converter em string valores compostos armazenados em shared data de JSON. O codec Rust retorna objetos decodificados, o que corresponde aos resultados dequery_npde ambos os codecs. - Uma alternativa
LowCardinalitydentro de um contêiner que se materializa por célula, comoArray(Variant(...)), produz células com valores iguais que não compartilham a identidade de objeto por slot de dicionário apresentada pelo codec Python. - Colunas
Nullable(Tuple(...))com um ou mais elementos são decodificadas corretamente no codec Rust. O codec Python interpreta esse layout de forma incorreta, e o resultado do Rust é o comportamento de referência. Ambos os codecs suportamNullable(Tuple()). rust_strictrejeita opções de consulta que o caminho Rust não implementa, comoquery_formatscustomizados por consulta, em vez de alterar o comportamento silenciosamente.- Erros de conversão e de validação de insert no Rust podem gerar
DataErroronde o codec Python geraValueError, e o texto da mensagem pode diferir. Entre os exemplos estão valoresTimeeTime64inválidos, endereços IPv6, dimensões de QBit, comprimentos deFixedString, stringsFloat64e tentativas de inserir elementos em uma colunaTuple(). - O codificador Rust rejeita
b""paraFixedString(N)e strings numéricas como"2"em colunas de inteiros. O codec Python preenche com zeros um valorFixedStringvazio e converte strings numéricas. - O codec Rust decodifica alguns valores de variante compartilhada de
Dynamicpara seus tipos Python nos casos em que o codec Python mantém o valor como raw bytes. Por exemplo, umDecimalarmazenado pode ser retornado comodecimal.Decimalno Rust e como um valor binário no Python. - Para valores
Dateno armazenamento compartilhado deDynamic,query_npequery_dfretornam célulasdatetime.datecom o codec Rust e célulasnumpy.datetime64com o codec Python. Ambos os codecs retornamdatetime.datea partir dequery.