QueryContexts
O ClickHouse Connect executa consultas padrão em um QueryContext. O QueryContext contém as principais estruturas usadas para montar consultas no banco de dados ClickHouse, bem como a configuração usada para processar o resultado em um QueryResult ou outra estrutura de dados de resposta. Isso inclui a própria consulta, parâmetros, configurações, formatos de leitura e outras propriedades.
Um QueryContext pode ser obtido usando o método create_query_context do cliente. Esse método aceita os mesmos parâmetros que o método principal de consulta. Esse contexto de consulta pode então ser passado aos métodos query, query_df ou query_np como o argumento nomeado context, em vez de alguns ou de todos os outros argumentos desses métodos. Observe que argumentos adicionais especificados na chamada do método substituirão quaisquer propriedades do QueryContext.
O caso de uso mais claro para um QueryContext é enviar a mesma consulta com valores diferentes para os parâmetros de associação. Todos os valores dos parâmetros podem ser atualizados chamando o método QueryContext.set_parameters com um dicionário, ou qualquer valor individual pode ser atualizado chamando QueryContext.set_parameter com o par key, value desejado.
qc = client.create_query_context(
query="SELECT {k:Int32}",
parameters={"k": 13},
)
result = client.query(context=qc)
assert result.first_row == (13,)
qc.set_parameter("k", 79)
result = client.query(context=qc)
assert result.first_row == (79,)Observe que QueryContexts não são thread-safe, mas é possível obter uma cópia em um ambiente multithread chamando o método QueryContext.updated_copy.
Consultas em streaming
O cliente ClickHouse Connect oferece vários métodos para recuperar dados como um stream (implementado como um gerador Python):
query_column_block_stream– Retorna os dados da consulta em blocos, como uma sequência de colunas, usando objetos nativos do Pythonquery_row_block_stream– Retorna os dados da consulta como um bloco de linhas, usando objetos nativos do Pythonquery_rows_stream– Retorna os dados da consulta como uma sequência de linhas, usando objetos nativos do Pythonquery_np_stream– Retorna cada bloco de dados da consulta do ClickHouse como um array NumPyquery_df_stream– Retorna cada bloco de dados da consulta do ClickHouse como um DataFrame do Pandasquery_arrow_stream– Retorna os dados da consulta como objetosRecordBatchdo PyArrowquery_df_arrow_stream– Retorna cada lote do Arrow como um DataFrame do Pandas ou do Polars, selecionado pordataframe_library
Cada método retorna um StreamContext que deve ser aberto com uma instrução with. Os métodos de streaming do cliente async usam await e são abertos com async with.
Blocos de dados
O ClickHouse Connect processa todos os dados do método principal query como um stream de blocos recebidos do servidor ClickHouse. Esses blocos são transmitidos de e para o ClickHouse no formato personalizado "Native". Um "bloco" é simplesmente uma sequência de colunas de dados binários, em que cada coluna contém o mesmo número de valores do tipo de dados especificado. (Como banco de dados colunar, o ClickHouse armazena esses dados de forma semelhante.) O tamanho de um bloco retornado por uma consulta é determinado por duas configurações do usuário que podem ser definidas em vários níveis (perfil de usuário, usuário, sessão ou consulta). São elas:
- max_block_size – Tamanho máximo do bloco em linhas.
- preferred_block_size_bytes – Tamanho preferencial do bloco em bytes.
Independentemente de preferred_block_size_bytes, nenhum bloco terá mais de max_block_size linhas. O tamanho real pode ser menor e não deve ser considerado estável.
Ao usar um dos métodos query_*_stream do Client, os resultados são retornados bloco a bloco. O ClickHouse Connect carrega apenas um bloco por vez. Isso permite processar grandes volumes de dados sem precisar carregar um conjunto de resultados grande inteiro na memória. Observe que a aplicação deve estar preparada para processar qualquer número de blocos, e o tamanho exato de cada bloco não pode ser controlado.
Buffer de dados HTTP para processamento lento
Se uma aplicação consumir blocos muito mais lentamente do que o servidor os produz, a conexão HTTP pode ser encerrada antes que o processamento seja concluído. Aumente a configuração comum http_buffer_size se a aplicação tiver memória suficiente para armazenar em buffer mais dados de resposta. O padrão é 10 MiB. Os bytes de resposta em lz4 e zstd permanecem comprimidos nesse buffer, o que aumenta sua capacidade efetiva.
StreamContexts
Cada um dos métodos query_*_stream (como query_row_block_stream) retorna um objeto StreamContext do ClickHouse, que combina um contexto e um gerador do Python. Este é o uso básico:
with client.query_row_block_stream(
"SELECT pickup, dropoff, pickup_longitude, pickup_latitude FROM taxi_trips"
) as stream:
for block in stream:
for row in block:
process_trip(row)Observe que tentar usar um StreamContext sem uma instrução with resultará em erro. Usar um contexto do Python garante que o stream (neste caso, uma resposta HTTP em streaming) seja fechado corretamente, mesmo que nem todos os dados sejam consumidos e/ou uma exceção seja gerada durante o processamento. Além disso, StreamContexts só podem ser usados uma vez para consumir o stream. Tentar usar um StreamContext depois que ele tiver sido encerrado resultará em StreamClosedError.
Se a conexão falhar enquanto um resultado estiver sendo lido, um StreamFailureError será gerado em vez de retornar silenciosamente um resultado truncado. Sua mensagem segue a configuração show_clickhouse_errors do cliente.
Você pode usar a propriedade source do StreamContext para acessar o objeto de resultado pai, que inclui nomes de colunas e tipos. Para a maioria dos streams, este é um QueryResult; os métodos query_np_stream e query_df_stream expõem um NumpyResult.
Tipos de streaming
O método query_column_block_stream retorna o bloco como uma sequência de dados de coluna armazenados como tipos de dados nativos do Python. Usando as consultas taxi_trips acima, os dados retornados serão uma lista em que cada elemento é outra lista (ou tupla) contendo todos os dados da coluna correspondente. Assim, block[0] seria uma tupla contendo apenas strings. Formatos orientados a colunas são mais usados para executar operações de agregação sobre todos os valores de uma coluna, como somar o total das tarifas.
O método query_row_block_stream retorna o bloco como uma sequência de linhas, como em um banco de dados relacional tradicional. Para viagens de táxi, os dados retornados serão uma lista em que cada elemento é outra lista representando uma linha de dados. Assim, block[0] conteria todos os campos da primeira viagem de táxi em ordem, block[1] conteria uma linha com todos os campos da segunda viagem de táxi, e assim por diante. Resultados orientados a linhas normalmente são usados para exibição ou para processos de transformação.
O método query_rows_stream avança automaticamente para o próximo bloco e produz uma linha por vez. Ele é a contraparte linha a linha de query_row_block_stream.
O método query_np_stream retorna cada bloco como um array NumPy. Quando todas as colunas do resultado compartilham o mesmo dtype do NumPy, o array é bidimensional, com shape (linhas, colunas). Resultados mistos são retornados como um array estruturado unidimensional ou usam o dtype object.
O método query_df_stream retorna cada bloco do ClickHouse como um DataFrame bidimensional do Pandas. Aqui está um exemplo que mostra que o objeto StreamContext pode ser usado como contexto de forma diferida (mas apenas uma vez).
df_stream = client.query_df_stream("SELECT * FROM hits")
column_names = df_stream.source.column_names
with df_stream:
for df in df_stream:
process_dataframe(df)O método query_df_arrow_stream converte batches do Arrow em DataFrames do Pandas ou do Polars. Selecione a biblioteca com dataframe_library, cujo valor padrão é "pandas".
Por fim, query_arrow_stream encapsula uma resposta ArrowStream do ClickHouse em um StreamContext. Cada iteração retorna um RecordBatch do PyArrow.
Exemplos de streaming
Fazer streaming de linhas
import clickhouse_connect
client = clickhouse_connect.get_client()
# Stream large result sets row by row
with client.query_rows_stream("SELECT number, number * 2 as doubled FROM system.numbers LIMIT 100000") as stream:
for row in stream:
print(row) # Process each row
# Output:
# (0, 0)
# (1, 2)
# (2, 4)
# Additional rows followFazer streaming de blocos de linhas
import clickhouse_connect
client = clickhouse_connect.get_client()
# Stream in blocks of rows (more efficient than row-by-row)
with client.query_row_block_stream("SELECT number, number * 2 FROM system.numbers LIMIT 100000") as stream:
for block in stream:
print(f"Received block with {len(block)} rows")Fazer streaming de DataFrames do Pandas
import clickhouse_connect
client = clickhouse_connect.get_client()
# Stream query results as Pandas DataFrames
with client.query_df_stream("SELECT number, toString(number) AS str FROM system.numbers LIMIT 100000") as stream:
for df in stream:
# Process each DataFrame block
print(f"Received DataFrame with {len(df)} rows")
print(df.head(3))Streaming de lotes de Arrow
import clickhouse_connect
client = clickhouse_connect.get_client()
# Stream query results as Arrow record batches
with client.query_arrow_stream("SELECT * FROM large_table") as stream:
for arrow_batch in stream:
# Process each Arrow batch
print(f"Received Arrow batch with {arrow_batch.num_rows} rows")Linhas do streaming assíncrono
import asyncio
import clickhouse_connect
async def main():
async_client = await clickhouse_connect.get_async_client()
async with await async_client.query_rows_stream(
"SELECT number FROM numbers(100000)"
) as stream:
async for row in stream:
print(row)
asyncio.run(main())Consultas com NumPy, Pandas e Arrow
O ClickHouse Connect oferece métodos de consulta especializados para trabalhar com estruturas de dados do NumPy, Pandas e Arrow. Esses métodos permitem recuperar os resultados das consultas diretamente nesses formatos de dados populares, sem necessidade de conversão manual.
Consultas com NumPy
O método query_np retorna os resultados da consulta como um array do NumPy em vez de um QueryResult do ClickHouse Connect.
import clickhouse_connect
client = clickhouse_connect.get_client()
# Query returns a NumPy array
np_array = client.query_np("SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 5")
print(type(np_array))
# Output:
# <class 'numpy.ndarray'>
print(np_array)
# Output:
# [[0 0]
# [1 2]
# [2 4]
# [3 6]
# [4 8]]Consultas com Pandas
O método query_df retorna os resultados da consulta como um DataFrame do Pandas, em vez de um QueryResult do ClickHouse Connect.
import clickhouse_connect
client = clickhouse_connect.get_client()
# Query returns a Pandas DataFrame
df = client.query_df("SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 5")
print(type(df))
# Output: <class 'pandas.core.frame.DataFrame'>
print(df)
# Output:
# number doubled
# 0 0 0
# 1 1 2
# 2 2 4
# 3 3 6
# 4 4 8Consultas com PyArrow
O método query_arrow retorna uma tabela PyArrow usando diretamente o formato de saída Arrow do ClickHouse. Ele aceita query, parameters, settings, external_data e transport_settings. A opção use_strings controla se as colunas String do ClickHouse são emitidas como strings do Arrow ou valores binários.
import clickhouse_connect
client = clickhouse_connect.get_client()
# Query returns a PyArrow Table
arrow_table = client.query_arrow("SELECT number, toString(number) AS str FROM system.numbers LIMIT 3")
print(type(arrow_table))
# Output:
# <class 'pyarrow.lib.Table'>
print(arrow_table)
# Output:
# pyarrow.Table
# number: uint64 not null
# str: string not null
# ----
# number: [[0,1,2]]
# str: [["0","1","2"]]DataFrames com Arrow como backend
O ClickHouse Connect oferece suporte à criação eficiente de DataFrames a partir de resultados Arrow por meio de query_df_arrow e query_df_arrow_stream. Esses métodos evitam a conversão por meio de objetos de linha do Python e reutilizam buffers Arrow quando a biblioteca de destino permite:
query_df_arrow: Executa a consulta usando o formato de saídaArrowdo ClickHouse e retorna um DataFrame.dataframe_library="pandas"retorna um DataFrame do Pandas 2.0 ou posterior usandopd.ArrowDtype.dataframe_library="polars"retorna um DataFrame do Polars criado por meio depl.from_arrow.
query_df_arrow_stream: Transmite lotes Arrow como DataFrames do Pandas ou do Polars.
Consulta para DataFrame com Arrow como backend
import clickhouse_connect
client = clickhouse_connect.get_client()
# Query returns a Pandas DataFrame with Arrow dtypes (requires pandas 2.x)
df = client.query_df_arrow(
"SELECT number, toString(number) AS str FROM system.numbers LIMIT 3",
dataframe_library="pandas"
)
print(df.dtypes)
# Output:
# number uint64[pyarrow]
# str string[pyarrow]
# dtype: object
# Or use Polars
polars_df = client.query_df_arrow(
"SELECT number, toString(number) AS str FROM system.numbers LIMIT 3",
dataframe_library="polars"
)
print(polars_df.dtypes)
# Output:
# [UInt64, String]
# Streaming into batches of DataFrames (polars shown)
with client.query_df_arrow_stream(
"SELECT number, toString(number) AS str FROM system.numbers LIMIT 100000", dataframe_library="polars"
) as stream:
for df_batch in stream:
print(f"Received {type(df_batch)} batch with {len(df_batch)} rows and dtypes: {df_batch.dtypes}")Observações e ressalvas
- O ClickHouse controla o esquema do Arrow. Tipos sem uma representação direta em Arrow podem ser retornados usando um tipo físico compatível, incluindo campos binários. Inspecione
table.schemaou os dtypes do DataFrame antes de aplicar conversões específicas da aplicação. - Resultados do Pandas com Arrow como backend exigem o Pandas 2.0 ou posterior.
use_stringscontrola se colunasStringdo ClickHouse usam campos de string do Arrow ou campos binários quando o servidor oferece suporte aoutput_format_arrow_string_as_string.tz_mode="schema"ainda não é compatível com métodos de consulta baseados em Arrow. Eles emitem um aviso e preservam os metadados de fuso horário fornecidos pela resposta do Arrow.
Formatos de leitura
Os formatos de leitura controlam os valores retornados por query, query_np e query_df. Eles não se aplicam aos métodos raw nem aos métodos Arrow, porque esses métodos usam diretamente um formato de saída do servidor. Por exemplo, definir o formato de leitura de UUID como "string" retorna strings UUID em vez de objetos uuid.UUID.
O argumento "tipo de dado" de qualquer função de formatação pode incluir curingas. O formato é uma única string em letras minúsculas. Wrappers de contêiner, como Array, Nullable e LowCardinality, preservam o formato selecionado para seu tipo de elemento.
Os formatos de leitura podem ser definidos em vários níveis:
- Globalmente, usando os métodos definidos no pacote
clickhouse_connect.datatypes.format. Isso controlará o formato do tipo de dado configurado para todas as consultas.
from clickhouse_connect.datatypes.format import set_read_format
# Return both IPv6 and IPv4 values as strings
set_read_format("IPv*", "string")
# Return all Date types as the underlying epoch second or epoch day
set_read_format("Date*", "int")- Para toda a consulta, usando o argumento de dicionário opcional
query_formats. Nesse caso, qualquer coluna (ou subcoluna) dos tipos de dados especificados usará o formato configurado.
# Return any UUID column as a string
client.query(
"SELECT user_id, user_uuid, device_uuid FROM users",
query_formats={"UUID": "string"},
)- Para uma coluna de resultado específica, use o dicionário opcional
column_formats. Cada chave é o nome de uma coluna retornada. Seu valor é uma string de formato ou um mapeamento aninhado de nomes de tipos do ClickHouse para formatos, o que é útil para Tuples, Maps e outros tipos de contêiner.
# Return IPv6 values in the `dev_address` column as strings
client.query(
"SELECT device_id, dev_address, gw_address FROM devices",
column_formats={"dev_address": "string"},
)Opções de formatos de leitura (tipos Python)
| Tipo do ClickHouse | Tipo Python nativo | Formatos de leitura | Comentários |
|---|---|---|---|
| Int[8-64], UInt[8-32] | int | string | |
| UInt64 | int | signed | No momento, o Superset não lida com valores UInt64 grandes sem sinal |
| [U]Int[128,256] | int | string | Os valores int do Pandas e do NumPy têm no máximo 64 bits, então podem ser retornados como strings |
| BFloat16 | float | - | Todos os floats em Python têm 64 bits internamente |
| Float32 | float | string | Todos os floats em Python têm 64 bits internamente |
| Float64 | float | string | |
| Decimal | decimal.Decimal | - | |
| String | str | bytes | As colunas String do ClickHouse não têm codificação inerente, então também são usadas para dados binários de comprimento variável |
| FixedString | bytes | string | FixedStrings são arrays de bytes de tamanho fixo, mas às vezes são tratados como strings em Python |
| Enum[8,16] | str | int | O formato nativo retorna rótulos; int retorna o inteiro subjacente. |
| Date | datetime.date | int | O formato inteiro retorna dias desde 1970-01-01. |
| Date32 | datetime.date | int | O formato inteiro retorna o deslocamento de dias com sinal mais amplo. |
| DateTime | datetime.datetime | int | O formato inteiro retorna segundos desde o epoch. |
| DateTime64 | datetime.datetime | int | O formato inteiro retorna ticks na precisão da coluna. O datetime do Python é limitado a microssegundos. |
| Time | datetime.timedelta | int, string, time | O formato inteiro retorna segundos. O formato time é limitado a valores que cabem em datetime.time. |
| Time64 | datetime.timedelta | int, string, time | O formato inteiro retorna ticks na precisão da coluna. O timedelta do Python é limitado a microssegundos. |
| IPv4 | ipaddress.IPv4Address |
string, int | Endereços IP podem ser lidos como strings ou inteiros. |
| IPv6 | ipaddress.IPv6Address |
string | Endereços IP podem ser lidos como strings e, quando formatados corretamente, podem ser inseridos como endereços IP |
| Tuple | dict ou tuple | tuple, dict, json | Tuplas nomeadas retornam dicionários por padrão; tuplas sem nome retornam tuplas. |
| Map | dict | - | |
| Nested | Sequence[dict] | - | |
| UUID | uuid.UUID | string | UUIDs podem ser lidos como strings formatadas de acordo com a RFC 4122 |
| JSON | dict | string | Um dicionário Python é retornado por padrão. O formato string retornará uma string JSON |
| Variant | object | typed | typed retorna TypedVariant(value, type_name) para preservar o tipo do membro de origem. |
| Dynamic | object | - | Retorna o tipo Python correspondente ao tipo de dado do ClickHouse armazenado para o valor |
| QBit | list[float] | - | O NumPy é usado automaticamente para uma transposição de bits mais rápida quando instalado. |
Dados externos
As consultas do ClickHouse podem aceitar dados externos em qualquer formato de entrada compatível. O cliente envia os dados como parte da requisição, e a consulta pode referenciá-los como uma tabela externa temporária. Consulte a documentação de dados externos do ClickHouse. Os métodos de consulta do cliente aceitam um objeto clickhouse_connect.driver.external.ExternalData por meio do parâmetro external_data.
| Nome | Tipo | Descrição |
|---|---|---|
| file_path | str | Caminho para um arquivo no sistema local, de onde os dados externos serão lidos. file_path ou data é obrigatório |
| file_name | str | O nome do "arquivo" de dados externos. Se não for fornecido, será obtido da parte do nome do arquivo em file_path. O nome da tabela externa é o nome do arquivo sem a extensão |
| data | bytes | Os dados externos em forma binária (em vez de serem lidos de um arquivo). data ou file_path é obrigatório |
| fmt | str | Formato de entrada dos dados no ClickHouse. O padrão é TSV |
| types | str or seq of str | Uma lista de tipos de dados das colunas nos dados externos. Se for uma string, os tipos devem ser separados por vírgulas. types ou structure é obrigatório |
| structure | str or seq of str | Uma lista de nomes de colunas + tipos de dados nos dados (veja os exemplos). structure ou types é obrigatório |
| mime_type | str | Tipo MIME opcional dos dados do arquivo. Atualmente, o ClickHouse ignora esse subcabeçalho HTTP |
Este exemplo faz uma junção entre um arquivo CSV externo e uma tabela directors armazenada no servidor:
import clickhouse_connect
from clickhouse_connect.driver.external import ExternalData
client = clickhouse_connect.get_client()
ext_data = ExternalData(
file_path="/data/movies.csv",
fmt="CSV",
structure=[
"movie String",
"year UInt16",
"rating Decimal32(3)",
"director String",
],
)
result = client.query(
"SELECT name, avg(rating) "
"FROM directors INNER JOIN movies ON directors.name = movies.director "
"GROUP BY directors.name",
external_data=ext_data,
).result_rowsArquivos de dados externos adicionais podem ser adicionados ao objeto ExternalData inicial usando o método add_file, que aceita os mesmos parâmetros do construtor. Em HTTP, todos os dados externos são transmitidos como parte de um upload de arquivo multi-part/form-data.
O backend chDB não oferece suporte a dados externos.
Fusos horários
Os valores DateTime e DateTime64 do ClickHouse são transmitidos como valores numéricos baseados em epoch. O ClickHouse Connect os converte em objetos datetime do Python usando metadados de coluna, substituições de consulta e a política de fuso horário do cliente.
O cliente tem duas opções independentes de fuso horário:
tz_sourceseleciona o fuso horário de fallback para colunas sem metadados explícitos de fuso horário:"auto"é o padrão. Usa o fuso horário do servidor quando o cliente consegue resolvê-lo com segurança em transições de horário de verão; caso contrário, usa o fuso horário local."server"sempre usa o fuso horário do servidor."local"sempre usa o fuso horário do processo local.
tz_modecontrola o tratamento de fuso horário:"naive_utc"é o padrão. Resultados em UTC e equivalentes a UTC são retornados como objetosdatetimesem fuso horário, para compatibilidade retroativa."aware"preserva otzinfode UTC e retorna valores UTC com fuso horário."schema"retorna valores com fuso horário somente quando o tipo da coluna declara um fuso horário, e valores sem fuso horário para colunasDateTime/DateTime64sem fuso horário.
Para consultas normais com "naive_utc" e "aware", o fuso horário ativo é selecionado nesta ordem:
- Uma substituição
column_tzspor coluna. - Metadados de fuso horário no tipo de coluna do ClickHouse.
- A substituição
query_tzpara toda a consulta. - Informações de fuso horário retornadas com a resposta HTTP.
- O fallback selecionado por
tz_source.
tz_mode="schema" ignora os fusos horários da consulta e de fallback, mas uma substituição column_tzs explícita ainda tem precedência.
result = client.query(
"SELECT "
"toDateTime('2026-01-15 12:00:00', 'UTC') AS utc_time, "
"toDateTime('2026-01-15 12:00:00', 'America/Denver') AS denver_time",
tz_mode="aware",
)
assert result.first_row[0].tzinfo is not None
assert result.first_row[1].tzinfo is not NoneOs nomes de fusos horários são resolvidos pelo módulo zoneinfo da biblioteca padrão. Instalações no Windows recebem tzdata automaticamente. Em imagens Linux mínimas sem um banco de dados de fusos horários da IANA, instale clickhouse-connect[tzdata].
Os resultados do Pandas preservam a resolução natural de cada tipo do ClickHouse, como datetime64[s] para DateTime e datetime64[ms] para DateTime64(3). Os métodos de DataFrame com Arrow como backend query_df_arrow e query_df_arrow_stream ainda não implementam tz_mode="schema" e emitirão um aviso quando isso for solicitado. query_arrow e query_arrow_stream retornam os metadados de fuso horário da resposta Arrow inalterados.