Pular para o conteúdo principal

Inserção de dados com ClickHouse Connect: uso avançado

InsertContexts

O ClickHouse Connect executa todas as inserções em um InsertContext. O InsertContext inclui todos os valores enviados como argumentos para o método insert do cliente. Além disso, quando um InsertContext é criado pela primeira vez, o ClickHouse Connect recupera os tipos de dados das colunas de inserção necessários para inserções eficientes no formato Native. Ao reutilizar o InsertContext em várias inserções, essa “pré-consulta” é evitada, e as inserções são executadas com mais rapidez e eficiência. Um InsertContext pode ser obtido usando o método create_insert_context do cliente. O método recebe os mesmos argumentos que a função insert. Observe que, para reutilização, apenas a propriedade data dos InsertContexts deve ser modificada. Isso está de acordo com seu propósito de fornecer um objeto reutilizável para inserções repetidas de novos dados na mesma tabela.
test_data = [[1, 'v1', 'v2'], [2, 'v3', 'v4']]
ic = test_client.create_insert_context(table='test_table', data='test_data')
client.insert(context=ic)
assert client.command('SELECT count() FROM test_table') == 2
new_data = [[3, 'v5', 'v6'], [4, 'v7', 'v8']]
ic.data = new_data
client.insert(context=ic)
qr = test_client.query('SELECT * FROM test_table ORDER BY key DESC')
assert qr.row_count == 4
assert qr[0][0] == 4
InsertContexts incluem estado mutável que é atualizado durante o processo de insert, portanto não são thread-safe.

Formatos de escrita

Atualmente, os formatos de escrita estão implementados para um número limitado de tipos. Na maioria dos casos, o ClickHouse Connect tentará determinar automaticamente o formato de escrita correto de uma coluna verificando o tipo do primeiro valor de dados não nulo. Por exemplo, ao inserir em uma coluna DateTime, se o primeiro valor inserido na coluna for um inteiro do Python, o ClickHouse Connect inserirá esse valor diretamente, partindo do pressuposto de que ele representa um segundo epoch. Na maioria dos casos, não é necessário substituir o formato de escrita de um tipo de dado, mas os métodos correspondentes no pacote clickhouse_connect.datatypes.format podem ser usados para fazer isso em nível global.

Opções de formato de escrita

ClickHouse TypeTipo nativo do PythonFormatos de escritaComentários
Int[8-64], UInt[8-32]int-
UInt64int
[U]Int[128,256]int
BFloat16float
Float32float
Float64float
Decimaldecimal.Decimal
Stringstring
FixedStringbytesstringSe inserido como string, os bytes adicionais serão preenchidos com zeros
Enum[8,16]string
Datedatetime.dateintO ClickHouse armazena valores Date como o número de dias desde 01/01/1970. Tipos int serão considerados esse valor de “data epoch”
Date32datetime.dateintIgual a Date, mas para um intervalo maior de datas
DateTimedatetime.datetimeintO ClickHouse armazena DateTime em segundos epoch. Tipos int serão considerados esse valor de “segundo epoch”
DateTime64datetime.datetimeintO datetime.datetime do Python é limitado à precisão de microssegundos. O valor bruto de int de 64 bits está disponível
Timedatetime.timedeltaint, string, timeO ClickHouse armazena DateTime em segundos epoch. Tipos int serão considerados esse valor de “segundo epoch”
Time64datetime.timedeltaint, string, timeO datetime.timedelta do Python é limitado à precisão de microssegundos. O valor bruto de int de 64 bits está disponível
IPv4ipaddress.IPv4AddressstringStrings formatadas corretamente podem ser inseridas como endereços IPv4
IPv6ipaddress.IPv6AddressstringStrings formatadas corretamente podem ser inseridas como endereços IPv6
Tupledict or tuple
Mapdict
NestedSequence[dict]
UUIDuuid.UUIDstringStrings formatadas corretamente podem ser inseridas como UUIDs do ClickHouse
JSON/Object(‘json’)dictstringTanto dicionários quanto strings JSON podem ser inseridos em colunas JSON (observe que Object('json') está obsoleto)
VariantobjectNo momento, todos os valores Variant são inseridos como Strings e analisados pelo servidor ClickHouse
DynamicobjectAviso — no momento, quaisquer inserções em uma coluna Dynamic são persistidas como String do ClickHouse

Métodos de inserção especializados

O ClickHouse Connect fornece métodos de inserção especializados para formatos de dados comuns:
  • insert_df — Insere um DataFrame do Pandas. Em vez de usar o argumento data como uma Sequence of Sequences do Python, o segundo parâmetro desse método exige um argumento df, que deve ser uma instância de DataFrame do Pandas. O ClickHouse Connect processa automaticamente o DataFrame como uma fonte de dados orientada por colunas, portanto o parâmetro column_oriented não é necessário nem está disponível.
  • insert_arrow — Insere uma tabela PyArrow. O ClickHouse Connect passa a tabela Arrow sem modificações para o servidor ClickHouse para processamento, portanto, além de table e arrow_table, apenas os argumentos database e settings estão disponíveis.
  • insert_df_arrow — Insere um DataFrame do Pandas com Arrow como backend ou um DataFrame do Polars. O ClickHouse Connect determinará automaticamente se o DataFrame é do tipo Pandas ou Polars. Se for Pandas, será feita uma validação para garantir que o backend dtype de cada coluna seja baseado em Arrow, e um erro será gerado se alguma não for.
Um array do NumPy é uma Sequence of Sequences válida e pode ser usado como argumento data no método principal insert, portanto não é necessário um método especializado.

Inserção de DataFrame do Pandas

import clickhouse_connect
import pandas as pd

client = clickhouse_connect.get_client()

df = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
})

client.insert_df("users", df)

Inserção de tabela PyArrow

import clickhouse_connect
import pyarrow as pa

client = clickhouse_connect.get_client()

arrow_table = pa.table({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
})

client.insert_arrow("users", arrow_table)

Inserção de DataFrame com Arrow como backend (pandas 2.x)

import clickhouse_connect
import pandas as pd

client = clickhouse_connect.get_client()

# Converte para dtypes com suporte a Arrow para melhor desempenho
df = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
}).convert_dtypes(dtype_backend="pyarrow")

client.insert_df_arrow("users", df)

Fusos horários

Ao inserir objetos datetime.datetime do Python em colunas DateTime ou DateTime64 do ClickHouse, o ClickHouse Connect trata automaticamente as informações de fuso horário. Como o ClickHouse armazena internamente todos os valores DateTime como timestamps Unix sem fuso horário (segundos ou frações de segundo desde a epoch), a conversão de fuso horário ocorre automaticamente no lado do cliente durante a inserção.

Objetos datetime com fuso horário

Se você inserir um objeto datetime.datetime do Python com fuso horário, o ClickHouse Connect chamará automaticamente .timestamp() para convertê-lo em um Unix timestamp, o que leva corretamente em conta o deslocamento do fuso horário. Isso significa que você pode inserir objetos datetime de qualquer fuso horário, e eles serão armazenados corretamente como o timestamp equivalente em UTC.
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()
client.command("CREATE TABLE events (event_time DateTime) ENGINE Memory")

# Inserir objetos datetime com fuso horário
denver_tz = pytz.timezone('America/Denver')
tokyo_tz = pytz.timezone('Asia/Tokyo')

data = [
    [datetime(2023, 6, 15, 10, 30, 0, tzinfo=pytz.UTC)],
    [denver_tz.localize(datetime(2023, 6, 15, 10, 30, 0))],
    [tokyo_tz.localize(datetime(2023, 6, 15, 10, 30, 0))]
]

client.insert('events', data, column_names=['event_time'])
results = client.query("SELECT * from events")
print(*results.result_rows, sep="\n")
# Saída:
# (datetime.datetime(2023, 6, 15, 10, 30),)
# (datetime.datetime(2023, 6, 15, 16, 30),)
# (datetime.datetime(2023, 6, 15, 1, 30),)
Neste exemplo, os três objetos datetime representam instantes diferentes, porque têm fusos horários diferentes. Cada um será convertido corretamente para o respectivo Unix timestamp e armazenado no ClickHouse.
Ao usar pytz, você deve usar o método localize() para adicionar informações de fuso horário a um datetime ingênuo. Passar tzinfo= diretamente para o construtor de datetime usará deslocamentos históricos incorretos. Para UTC, tzinfo=pytz.UTC funciona corretamente. Consulte a documentação do pytz para mais informações.

Objetos datetime sem informação de fuso horário

Se você inserir um objeto datetime.datetime do Python sem informação de fuso horário (ou seja, sem tzinfo), o método .timestamp() o interpretará como se estivesse no fuso horário local do sistema. Para evitar ambiguidades, recomenda-se:
  1. Sempre usar objetos datetime com fuso horário ao inserir, ou
  2. Garantir que o fuso horário do sistema esteja definido como UTC, ou
  3. Converter manualmente para timestamps epoch antes de inserir
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()

# Recomendado: sempre use datetimes com fuso horário definido
utc_time = datetime(2023, 6, 15, 10, 30, 0, tzinfo=pytz.UTC)
client.insert('events', [[utc_time]], column_names=['event_time'])

# Alternativa: converter para epoch timestamp manualmente
naive_time = datetime(2023, 6, 15, 10, 30, 0)
epoch_timestamp = int(naive_time.replace(tzinfo=pytz.UTC).timestamp())
client.insert('events', [[epoch_timestamp]], column_names=['event_time'])

Colunas DateTime com metadados de fuso horário

As colunas do ClickHouse podem ser definidas com metadados de fuso horário (por exemplo, DateTime('America/Denver') ou DateTime64(3, 'Asia/Tokyo')). Esses metadados não afetam a forma como os dados são armazenados (ainda como timestamps UTC), mas controlam o fuso horário usado ao consultar os dados no ClickHouse. Ao inserir dados nessas colunas, o ClickHouse Connect converte seu datetime do Python em um Unix timestamp (considerando o fuso horário, se houver). Ao consultar os dados novamente, o ClickHouse Connect retorna o datetime convertido para o fuso horário da coluna, independentemente do fuso horário usado na inserção.
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()

# Cria tabela com metadados de fuso horário de Los Angeles
client.command("CREATE TABLE events (event_time DateTime('America/Los_Angeles')) ENGINE Memory")

# Insere um horário de Nova York (10:30 AM EDT, que é 14:30 UTC)
ny_tz = pytz.timezone("America/New_York")
data = ny_tz.localize(datetime(2023, 6, 15, 10, 30, 0))
client.insert("events", [[data]], column_names=["event_time"])

# Ao consultar, o horário é automaticamente convertido para o fuso horário de Los Angeles
# 10:30 AM Nova York (UTC-4) = 14:30 UTC = 7:30 AM Los Angeles (UTC-7)
results = client.query("select * from events")
print(*results.result_rows, sep="\n")
# Saída:
# (datetime.datetime(2023, 6, 15, 7, 30, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>),)

Inserções de arquivos

O pacote clickhouse_connect.driver.tools inclui o método insert_file, que permite inserir dados diretamente do sistema de arquivos em uma tabela existente do ClickHouse. O parsing é delegado ao servidor ClickHouse. insert_file aceita os seguintes parâmetros:
ParâmetroTipoPadrãoDescrição
clientClientObrigatórioO driver.Client usado para realizar a inserção
tablestrObrigatórioA tabela do ClickHouse na qual os dados serão inseridos. O nome completo da tabela (incluindo o banco de dados) é permitido.
file_pathstrObrigatórioO caminho nativo no sistema de arquivos para o arquivo de dados
fmtstrCSV, CSVWithNamesO formato de entrada do ClickHouse do arquivo. CSVWithNames é assumido se column_names não for fornecido
column_namesSequence of strNoneUma lista de nomes de colunas no arquivo de dados. Não é necessária para formatos que incluem nomes de colunas
databasestrNoneBanco de dados da tabela. Ignorado se a tabela estiver totalmente qualificada. Se não for especificado, a inserção usará o banco de dados do cliente
settingsdictNoneVeja a descrição das configurações.
compressionstrNoneUm tipo de compressão do ClickHouse reconhecido (zstd, lz4, gzip) usado no cabeçalho HTTP Content-Encoding
Para arquivos com dados inconsistentes ou valores de data/hora em um formato incomum, este método reconhece configurações aplicáveis a importações de dados (como input_format_allow_errors_num e input_format_allow_errors_num).
import clickhouse_connect
from clickhouse_connect.driver.tools import insert_file

client = clickhouse_connect.get_client()
insert_file(client, 'example_table', 'my_data.csv',
            settings={'input_format_allow_errors_ratio': .2,
                      'input_format_allow_errors_num': 5})
Última modificação em 10 de junho de 2026