Перейти к основному содержанию

QueryContexts

ClickHouse Connect выполняет стандартные запросы в контексте QueryContext. QueryContext содержит ключевые структуры, используемые для построения запросов к базе данных ClickHouse, а также конфигурацию, которая используется для преобразования результата в QueryResult или другую структуру данных ответа. Сюда входят сам запрос, параметры, настройки, форматы чтения и другие свойства. QueryContext можно получить с помощью клиентского метода create_query_context. Этот метод принимает те же параметры, что и основной метод запроса. Затем этот контекст можно передать в методы query, query_df или query_np как именованный аргумент context вместо части или всех остальных аргументов этих методов. Обратите внимание, что дополнительные аргументы, указанные при вызове метода, переопределяют любые свойства QueryContext. Наиболее понятный сценарий использования QueryContext — отправка одного и того же запроса с разными значениями параметров привязки. Все значения параметров можно обновить, вызвав метод QueryContext.set_parameters и передав ему словарь, а любое отдельное значение — вызвав QueryContext.set_parameter с нужной парой key, value.
client.create_query_context(query='SELECT value1, value2 FROM data_table WHERE key = {k:Int32}',
                            parameters={'k': 2},
                            column_oriented=True)
result = client.query(context=qc)
assert result.result_set[1][0] == 'second_value2'
qc.set_parameter('k', 1)
result = test_client.query(context=qc)
assert result.result_set[1][0] == 'first_value2'
Обратите внимание, что объекты QueryContext не являются потокобезопасными, однако в многопоточной среде можно получить их копию, вызвав метод QueryContext.updated_copy.

Стриминг запросов

Клиент ClickHouse Connect предоставляет несколько методов для получения данных в виде потока (реализованного как генератор Python):
  • query_column_block_stream — Возвращает данные запроса блоками как последовательность столбцов с использованием собственных объектов Python
  • query_row_block_stream — Возвращает данные запроса как блок строк с использованием собственных объектов Python
  • query_rows_stream — Возвращает данные запроса как последовательность строк с использованием собственных объектов Python
  • query_np_stream — Возвращает каждый блок данных запроса ClickHouse как массив NumPy
  • query_df_stream — Возвращает каждый блок данных запроса ClickHouse как DataFrame Pandas
  • query_arrow_stream — Возвращает данные запроса в виде PyArrow RecordBlocks
  • query_df_arrow_stream — Возвращает каждый блок данных запроса ClickHouse как DataFrame Pandas на базе Arrow или как DataFrame Polars в зависимости от аргумента dataframe_library (по умолчанию — “pandas”).
Каждый из этих методов возвращает объект ContextStream, который необходимо открыть с помощью оператора with, чтобы начать чтение потока.

Блоки данных

ClickHouse Connect обрабатывает все данные из основного метода query как поток блоков, получаемых от сервер ClickHouse. Эти блоки передаются в собственном формате “Native” в ClickHouse и из ClickHouse. «Блок» — это просто последовательность столбцов бинарных данных, где каждый столбец содержит одинаковое количество значений указанного типа данных. (Поскольку ClickHouse — колоночная база данных, он хранит эти данные в похожем виде.) Размер блока, возвращаемого запросом, определяется двумя пользовательскими настройками, которые можно задавать на нескольких уровнях (профиль пользователя, пользователь, сеанс или запрос). Вот они:
  • max_block_size — Ограничение на размер блока в строках. По умолчанию — 65536.
  • preferred_block_size_bytes — Мягкое ограничение на размер блока в байтах. По умолчанию — 1,000,0000.
Независимо от preferred_block_size_setting, каждый блок никогда не будет содержать более max_block_size строк. В зависимости от типа запроса фактически возвращаемые блоки могут быть любого размера. Например, запросы к distributed таблице, охватывающей много сегментов, могут содержать блоки меньшего размера, полученные напрямую из каждого сегмента. При использовании одного из методов клиента query_*_stream результаты возвращаются по блокам. ClickHouse Connect загружает только один блок за раз. Это позволяет обрабатывать большие объёмы данных без необходимости загружать в память весь большой результирующий набор. Обратите внимание: приложение должно быть готово обработать любое количество блоков, а точный размер каждого блока нельзя контролировать.

HTTP-буфер данных для медленной обработки

Из-за ограничений HTTP-протокола, если блоки обрабатываются со скоростью, значительно ниже той, с которой сервер ClickHouse передает данные в потоковом режиме, сервер ClickHouse закроет соединение, и в потоке обработки будет сгенерировано исключение. Частично эту проблему можно смягчить, увеличив размер буфера для потоковой передачи по HTTP (по умолчанию 10 мегабайт) с помощью общей настройки http_buffer_size. В этой ситуации большие значения http_buffer_size допустимы, если приложению доступно достаточно памяти. Данные в буфере хранятся в сжатом виде при использовании сжатия lz4 или zstd, поэтому эти типы сжатия увеличивают общий доступный размер буфера.

StreamContexts

Каждый из методов query_*_stream (например, query_row_block_stream) возвращает объект ClickHouse StreamContext, который сочетает в себе Python-контекст и генератор. Вот базовое использование:
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:
            <выполнить действие с каждой строкой данных о поездке на Python>
Обратите внимание: попытка использовать StreamContext без оператора with вызовет ошибку. Использование контекста Python гарантирует, что поток (в данном случае — потоковый HTTP-ответ) будет корректно закрыт, даже если будут прочитаны не все данные и/или в ходе обработки возникнет исключение. Кроме того, StreamContext можно использовать для чтения потока только один раз. Попытка использовать StreamContext после выхода из него приведёт к ошибке StreamClosedError. Вы можете использовать свойство source объекта StreamContext, чтобы получить доступ к родительскому объекту QueryResult, который содержит имена столбцов и типы.

Типы потоков

Метод query_column_block_stream возвращает блок как последовательность данных столбцов в нативных типах данных Python. Если использовать приведённые выше запросы taxi_trips, возвращённые данные будут представлять собой список, где каждый элемент — это ещё один список (или кортеж), содержащий все данные соответствующего столбца. То есть block[0] будет кортежем, содержащим только строковые значения. Форматы с ориентацией по столбцам чаще всего используются для выполнения агрегатных операций над всеми значениями в столбце, например для подсчёта общей стоимости поездок. Метод query_row_block_stream возвращает блок как последовательность строк, как в традиционной реляционной базе данных. Для поездок на такси возвращённые данные будут представлять собой список, где каждый элемент — это ещё один список, представляющий строку данных. То есть block[0] будет содержать все поля (по порядку) для первой поездки на такси, block[1] — строку со всеми полями второй поездки на такси, и так далее. Результаты с ориентацией по строкам обычно используются для отображения или преобразования данных. query_row_stream — это вспомогательный метод, который автоматически переходит к следующему блоку при итерации по потоку. В остальном он идентичен query_row_block_stream. Метод query_np_stream возвращает каждый блок как двумерный массив NumPy. Внутри массивы NumPy (как правило) хранятся по столбцам, поэтому отдельные методы для строк и столбцов не нужны. «Форма» массива NumPy будет выражена как (столбцы, строки). Библиотека NumPy предоставляет множество методов для работы с массивами NumPy. Обратите внимание: если все столбцы в запросе имеют один и тот же NumPy dtype, то и возвращённый массив NumPy тоже будет иметь только один dtype, и его можно будет переупорядочивать по форме/поворачивать без фактического изменения его внутренней структуры. Метод query_df_stream возвращает каждый блок ClickHouse как двумерный Pandas DataFrame. Ниже приведён пример, показывающий, что объект StreamContext можно использовать как контекстный менеджер в отложенном режиме (но только один раз).
df_stream = client.query_df_stream('SELECT * FROM hits')
column_names = df_stream.source.column_names
with df_stream:
    for df in df_stream:
        <do something with the pandas DataFrame>
Метод query_df_arrow_stream возвращает каждый блок ClickHouse в виде DataFrame с dtype-бэкендом PyArrow. Этот метод поддерживает DataFrame как в Pandas (2.x и выше), так и в Polars через параметр dataframe_library (по умолчанию — "pandas"). На каждой итерации выдаётся DataFrame, преобразованный из record batch PyArrow, что обеспечивает более высокую производительность и более эффективное использование памяти для некоторых типов данных. Наконец, метод query_arrow_stream возвращает результат ClickHouse в формате ArrowStream в виде pyarrow.ipc.RecordBatchStreamReader, обёрнутого в StreamContext. На каждой итерации потока возвращается PyArrow RecordBlock.

Примеры стриминга

Поток строк

import clickhouse_connect

client = clickhouse_connect.get_client()

# Потоковая передача больших результирующих наборов строка за строкой
with client.query_rows_stream("SELECT number, number * 2 as doubled FROM system.numbers LIMIT 100000") as stream:
    for row in stream:
        print(row)  # Обработка каждой строки
        # Вывод:
        # (0, 0)
        # (1, 2)
        # (2, 4)
        # ....

Потоковая передача блоков со строками

import clickhouse_connect

client = clickhouse_connect.get_client()

# Потоковая передача блоками строк (эффективнее, чем построчная)
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")
        # Вывод:
        # Получен блок из 65409 строк
        # Получен блок из 34591 строк

Потоковая передача Pandas DataFrame

import clickhouse_connect

client = clickhouse_connect.get_client()

# Потоковая передача результатов запроса в виде Pandas DataFrame
with client.query_df_stream("SELECT number, toString(number) AS str FROM system.numbers LIMIT 100000") as stream:
    for df in stream:
        # Обработка каждого блока DataFrame
        print(f"Received DataFrame with {len(df)} rows")
        print(df.head(3))
        # Вывод:
        # Получен DataFrame с 65409 строками
        #    number str
        # 0       0   0
        # 1       1   1
        # 2       2   2
        # Получен DataFrame с 34591 строками
        #    number    str
        # 0   65409  65409
        # 1   65410  65410
        # 2   65411  65411

Потоковая передача батчей Arrow

import clickhouse_connect

client = clickhouse_connect.get_client()

# Потоковая передача результатов запроса в виде батчей записей Arrow
with client.query_arrow_stream("SELECT * FROM large_table") as stream:
    for arrow_batch in stream:
        # Обработка каждого батча Arrow
        print(f"Received Arrow batch with {arrow_batch.num_rows} rows")
        # Вывод:
        # Получен батч Arrow с 65409 строками
        # Получен батч Arrow с 34591 строкой

Запросы NumPy, Pandas и Arrow

ClickHouse Connect предоставляет специализированные методы для работы со структурами данных NumPy, Pandas и Arrow. Эти методы позволяют получать результаты запроса напрямую в этих популярных форматах данных без ручного преобразования.

Запросы NumPy

Метод query_np возвращает результаты запроса в виде массива NumPy, а не объекта ClickHouse Connect QueryResult.
import clickhouse_connect

client = clickhouse_connect.get_client()

# Запрос возвращает массив NumPy
np_array = client.query_np("SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 5")

print(type(np_array))
# Вывод:
# <class "numpy.ndarray">

print(np_array)
# Вывод:
# [[0 0]
#  [1 2]
#  [2 4]
#  [3 6]
#  [4 8]]

Запросы Pandas

Метод query_df возвращает результаты запроса в виде объекта Pandas DataFrame, а не ClickHouse Connect QueryResult.
import clickhouse_connect

client = clickhouse_connect.get_client()

# Запрос возвращает Pandas DataFrame
df = client.query_df("SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 5")

print(type(df))
# Вывод: <class "pandas.core.frame.DataFrame">
print(df)
# Вывод:
#    number  doubled
# 0       0        0
# 1       1        2
# 2       2        4
# 3       3        6
# 4       4        8

Запросы PyArrow

Метод query_arrow возвращает результаты запроса в виде таблицы PyArrow. Он напрямую использует формат ClickHouse Arrow, поэтому из аргументов основного метода query поддерживает только три: query, parameters и settings. Кроме того, есть дополнительный аргумент use_strings, который определяет, будут ли типы ClickHouse String в таблице Arrow представлены как строки (если True) или как байты (если False).
import clickhouse_connect

client = clickhouse_connect.get_client()

# Запрос возвращает таблицу PyArrow
arrow_table = client.query_arrow("SELECT number, toString(number) AS str FROM system.numbers LIMIT 3")

print(type(arrow_table))
# Вывод:
# <class "pyarrow.lib.Table">

print(arrow_table)
# Вывод:
# pyarrow.Table
# number: uint64 not null
# str: string not null
# ----
# number: [[0,1,2]]
# str: [["0","1","2"]]

DataFrame на основе Arrow

ClickHouse Connect поддерживает быстрое и экономное по памяти создание DataFrame из результатов Arrow с помощью методов query_df_arrow и query_df_arrow_stream. Это тонкие обёртки над методами Arrow-запросов, которые по возможности выполняют преобразование в DataFrame без копирования:
  • query_df_arrow: Выполняет запрос, используя выходной формат ClickHouse Arrow, и возвращает DataFrame.
    • Для dataframe_library='pandas' возвращает DataFrame pandas 2.x с типами данных на основе Arrow (pd.ArrowDtype). Для этого требуется pandas 2.x; где возможно, используются буферы без копирования, что обеспечивает высокую производительность и низкие накладные расходы по памяти.
    • Для dataframe_library='polars' возвращает DataFrame Polars, созданный из таблицы Arrow (pl.from_arrow); он также работает эффективно и в зависимости от данных может не требовать копирования.
  • query_df_arrow_stream: Передаёт результаты потоком как последовательность DataFrame (pandas 2.x или Polars), преобразованных из батчей потока Arrow.

Запрос к DataFrame на базе Arrow

import clickhouse_connect

client = clickhouse_connect.get_client()

# Запрос возвращает Pandas DataFrame с типами Arrow (требуется 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)
# Вывод:
# number    uint64[pyarrow]
# str       string[pyarrow]
# dtype: object

# Или используйте Polars
polars_df = client.query_df_arrow(
    "SELECT number, toString(number) AS str FROM system.numbers LIMIT 3",
    dataframe_library="polars"
)
print(df.dtypes)
# Вывод:
# [UInt64, String]

# Потоковая передача батчами DataFrames (показано для polars)
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}")
        # Вывод:
        # Received <class 'polars.dataframe.frame.DataFrame'> batch with 65409 rows and dtypes: [UInt64, String]
        # Received <class 'polars.dataframe.frame.DataFrame'> batch with 34591 rows and dtypes: [UInt64, String]

Примечания и ограничения

  • Сопоставление типов Arrow: при возврате данных в формате Arrow ClickHouse сопоставляет типы с ближайшими поддерживаемыми типами Arrow. Для некоторых типов ClickHouse нет прямого эквивалента в Arrow, поэтому они возвращаются как необработанные байты в полях Arrow (обычно BINARY или FIXED_SIZE_BINARY).
    • Примеры: IPv4 представляется как Arrow UINT32; IPv6 и большие целые числа (Int128/UInt128/Int256/UInt256) часто представляются как FIXED_SIZE_BINARY/BINARY с необработанными байтами.
    • В таких случаях столбец DataFrame будет содержать байтовые значения из поля Arrow; интерпретация или преобразование этих байтов в соответствии с семантикой ClickHouse выполняется на стороне клиентского кода.
  • Неподдерживаемые типы данных Arrow (например, UUID/ENUM как полноценные типы Arrow) не выводятся; при выводе значения представляются с использованием ближайшего поддерживаемого типа Arrow (часто в виде бинарных байтов).
  • Требование Pandas: типы данных на базе Arrow требуют pandas 2.x. Для более старых версий pandas используйте query_df (без Arrow).
  • Строки и двоичные данные: параметр use_strings (если он поддерживается настройкой сервера output_format_arrow_string_as_string) определяет, будут ли столбцы ClickHouse String возвращаться как строки Arrow или как двоичные данные.

Примеры преобразования типов ClickHouse/Arrow при несовпадении

Когда ClickHouse возвращает столбцы в виде необработанных бинарных данных (например, FIXED_SIZE_BINARY или BINARY), преобразование этих байтов в подходящие типы Python выполняет прикладной код. Примеры ниже показывают, что некоторые преобразования удобно выполнять через API библиотеки DataFrame, тогда как в других случаях могут понадобиться чисто Python-решения, такие как struct.unpack (они уступают в производительности, но сохраняют гибкость). Столбцы Date могут приходить как UINT16 (число дней с эпохи Unix, 1970‑01‑01). Преобразование внутри DataFrame эффективно и выполняется просто:
# Polars
df = df.with_columns(pl.col("event_date").cast(pl.Date))

# Pandas
df["event_date"] = pd.to_datetime(df["event_date"], unit="D")
Столбцы типа Int128 могут поступать в виде FIXED_SIZE_BINARY с сырыми байтами. Polars нативно поддерживает 128-битные целые числа:
# Polars — встроенная поддержка
df = df.with_columns(pl.col("data").bin.reinterpret(dtype=pl.Int128, endianness="little"))
Начиная с NumPy 2.3, публичного dtype для 128-битных целых чисел нет, поэтому приходится использовать чистый Python — например, так:
# Предполагаем, что у нас есть pandas dataframe со столбцом Int128 типа fixed_size_binary[16][pyarrow]

print(df)
# Вывод:
#   str_col                                        int_128_col
# 0    num1  b'\\x15}\\xda\\xeb\\x18ZU\\x0fn\\x05\\x01\\x00\\x00\\x00...
# 1    num2  b'\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00...
# 2    num3  b'\\x15\\xdfp\\x81r\\x9f\\x01\\x00\\x00\\x00\\x00\\x00\\x...

print([int.from_bytes(n, byteorder="little") for n in df["int_128_col"].to_list()])
# Вывод:
# [1234567898765432123456789, 8, 456789123456789]
Главный вывод: прикладной код должен выполнять эти преобразования с учетом возможностей выбранной библиотеки DataFrame и допустимых компромиссов в производительности. Если преобразования, встроенные в DataFrame, недоступны, можно использовать подходы на чистом Python.

Форматы чтения

Форматы чтения определяют типы данных значений, возвращаемых методами клиента query, query_np и query_df. (raw_query и query_arrow не изменяют данные, поступающие из ClickHouse, поэтому управление форматами к ним не применяется.) Например, если формат чтения для UUID изменён со стандартного формата native на альтернативный string, значения столбца UUID в результате запроса к ClickHouse будут возвращаться как строки (в стандартном формате RFC 1422 8-4-4-4-12), а не как объекты Python UUID. Аргумент “тип данных” для любой функции форматирования может включать подстановочные шаблоны. Формат представляет собой одну строку в нижнем регистре. Форматы чтения можно задавать на нескольких уровнях:
  • Глобально, с помощью методов, определённых в пакете clickhouse_connect.datatypes.format. Это будет задавать формат для настроенного типа данных во всех запросах.
from clickhouse_connect.datatypes.format import set_read_format

# Возвращать значения IPv6 и IPv4 в виде строк
set_read_format('IPv*', 'string')

# Возвращать все типы Date как количество секунд или дней от начала эпохи
set_read_format('Date*', 'int')
  • Для всего запроса — с использованием необязательного аргумента словаря query_formats. В этом случае любой столбец (или подстолбец) указанных типов данных будет использовать заданный формат.
# Вернуть любой столбец UUID в виде строки
client.query('SELECT user_id, user_uuid, device_uuid from users', query_formats={'UUID': 'string'})
  • Для значений в конкретном столбце — с использованием необязательного аргумента словаря column_formats. Ключом служит имя столбца в том виде, в котором его возвращает ClickHouse, а значением — формат для столбца данных или вложенный словарь второго уровня “format”, где ключом является имя типа ClickHouse, а значением — форматы запроса. Этот вторичный словарь можно использовать для вложенных типов столбцов, таких как Tuples или Maps.
# Возвращать значения IPv6 в столбце `dev_address` в виде строк
client.query('SELECT device_id, dev_address, gw_address from devices', column_formats={'dev_address':'string'})

Параметры формата чтения (типы Python)

Тип ClickHouseНативный тип PythonФорматы чтенияКомментарии
Int[8-64], UInt[8-32]int-
UInt64intsignedВ настоящее время Superset не обрабатывает большие беззнаковые значения UInt64
[U]Int[128,256]intstringЗначения int в Pandas и NumPy ограничены 64 битами, поэтому они могут возвращаться как строки
BFloat16float-Все значения float в Python внутренне являются 64-битными
Float32float-Все значения float в Python внутренне являются 64-битными
Float64float-
Decimaldecimal.Decimal-
StringstringbytesУ столбцов String в ClickHouse нет встроенной кодировки, поэтому они также используются для двоичных данных переменной длины
FixedStringbytesstringFixedString — это массивы байтов фиксированного размера, но иногда они интерпретируются как строки Python
Enum[8,16]stringstring, intПеречисления Python не поддерживают пустые строки, поэтому все enum возвращаются либо как строки, либо как базовые значения int.
Datedatetime.dateintClickHouse хранит Date как количество дней с 01/01/1970. Это значение доступно как int
Date32datetime.dateintТо же, что и Date, но для более широкого диапазона дат
DateTimedatetime.datetimeintClickHouse хранит DateTime как количество секунд с начала epoch. Это значение доступно как int
DateTime64datetime.datetimeintТочность Python datetime.datetime ограничена микросекундами. Доступно исходное 64-битное значение int
Timedatetime.timedeltaint, string, timeМомент времени сохраняется как Unix-временная метка. Это значение доступно как int
Time64datetime.timedeltaint, string, timeТочность Python datetime.timedelta ограничена микросекундами. Доступно исходное 64-битное значение int
IPv4ipaddress.IPv4AddressstringIP-адреса можно читать как строки, а строки в корректном формате — вставлять как IP-адреса
IPv6ipaddress.IPv6AddressstringIP-адреса можно читать как строки, а строки в корректном формате — вставлять как IP-адреса
Tupledict or tupletuple, jsonИменованные кортежи по умолчанию возвращаются как словари. Именованные кортежи также могут возвращаться как строки JSON
Mapdict-
NestedSequence[dict]-
UUIDuuid.UUIDstringUUID можно читать как строки, отформатированные в соответствии с RFC 4122
JSONdictstringПо умолчанию возвращается словарь Python. Формат string возвращает строку JSON
Variantobject-Возвращает соответствующий тип Python для типа данных ClickHouse, в котором хранится значение
Dynamicobject-Возвращает соответствующий тип Python для типа данных ClickHouse, в котором хранится значение

Внешние данные

Запросы ClickHouse могут принимать внешние данные в любом формате ClickHouse. Эти двоичные данные отправляются вместе со строкой запроса и используются при обработке данных. Подробности о возможности External Data приведены здесь. Методы клиента query* принимают необязательный параметр external_data, позволяющий использовать эту возможность. Значением параметра external_data должен быть объект clickhouse_connect.driver.external.ExternalData. Конструктор этого объекта принимает следующие аргументы:
ИмяТипОписание
file_pathstrПуть к файлу в локальной файловой системе, из которого считываются внешние данные. Необходимо указать либо file_path, либо data
file_namestrИмя “файла” внешних данных. Если не указано, будет определено по file_path (без расширения)
databytesВнешние данные в двоичной форме (вместо чтения из файла). Необходимо указать либо data, либо file_path
fmtstrВходной формат ClickHouse для данных. По умолчанию используется TSV
typesstr or seq of strСписок типов данных столбцов во внешних данных. Если передана строка, типы должны быть разделены запятыми. Необходимо указать либо types, либо structure
structurestr or seq of strСписок имен столбцов и типов данных в данных (см. примеры). Необходимо указать либо structure, либо types
mime_typestrНеобязательный MIME-тип данных файла. В настоящее время ClickHouse игнорирует этот HTTP-подзаголовок
Чтобы отправить запрос с внешним CSV-файлом, содержащим данные о фильмах, и объединить эти данные с таблицей directors, уже существующей на сервере ClickHouse:
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_rows
Дополнительные внешние файлы данных можно добавить в исходный объект ExternalData с помощью метода add_file, который принимает те же параметры, что и конструктор. При использовании HTTP все внешние данные передаются в составе загрузки файла multi-part/form-data.

Часовые пояса

Существует несколько механизмов применения часового пояса к значениям ClickHouse DateTime и DateTime64. Внутренне сервер ClickHouse всегда хранит любой объект DateTime или DateTime64 как число без привязки к часовому поясу, представляющее секунды с начала эпохи 1970-01-01 00:00:00 UTC. Для значений DateTime64 представление может быть в миллисекундах, микросекундах или наносекундах с начала эпохи в зависимости от precision. В результате любая информация о часовом поясе всегда применяется на стороне клиента. Обратите внимание, что это требует дополнительных вычислений, поэтому в приложениях, критичных к производительности, рекомендуется рассматривать типы DateTime как временные метки эпохи, за исключением отображения для пользователя и преобразования (например, Pandas Timestamps всегда представляют собой 64-битное целое число, обозначающее наносекунды с начала эпохи, для повышения производительности). При использовании в запросах типов данных с учетом часового пояса — в частности, объекта Python datetime.datetimeclickhouse-connect применяет часовой пояс на стороне клиента по следующим правилам приоритета:
  1. Если для запроса указан parameter метода client_tzs, применяется часовой пояс конкретного столбца
  2. Если у столбца ClickHouse есть метаданные timezone (то есть это тип вроде DateTime64(3, ‘America/Denver’)), применяется часовой пояс столбца ClickHouse. (Обратите внимание, что эти метаданные timezone недоступны для clickhouse-connect для столбцов DateTime в версиях ClickHouse до 23.2)
  3. Если для запроса указан parameter метода query_tz, применяется «часовой пояс запроса».
  4. Если к запросу или сеансу применена настройка timezone, применяется этот часовой пояс. (Эта функциональность еще не выпущена в сервер ClickHouse)
  5. Наконец, если parameter клиента apply_server_timezone установлен в True (по умолчанию), применяется часовой пояс сервер ClickHouse.
Обратите внимание, что если примененный по этим правилам часовой пояс — UTC, clickhouse-connect всегда вернет объект Python datetime.datetime без привязки к часовому поясу. При необходимости прикладной код затем может добавить к этому объекту дополнительную информацию о часовом поясе.
Последнее изменение 10 июня 2026 г.