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

Интеграция Python с ClickHouse Connect

Введение

ClickHouse Connect — это основной драйвер базы данных, обеспечивающий взаимосвязь с широким спектром приложений на Python.

  • Основной интерфейс — это объект Client в пакете clickhouse_connect.driver. Этот корневой пакет также включает различные вспомогательные классы и утилиты, используемые для взаимодействия с сервером ClickHouse и реализации "контекста" для управления вставками и выборками запросов.
  • Пакет clickhouse_connect.datatypes предоставляет базовую реализацию и подклассы всех неэкспериментальных типов данных ClickHouse. Его основная функция — это сериализация и десериализация данных ClickHouse в бине формат "Native", используемый для достижения наиболее эффективного транспорта между ClickHouse и клиентскими приложениями.
  • Классы Cython/C в пакете clickhouse_connect.cdriver оптимизируют некоторые из наиболее распространенных сериализаций и десериализаций для значительного повышения производительности по сравнению с чистым Python.
  • В пакете clickhouse_connect.cc_sqlalchemy имеется ограниченный диалект SQLAlchemy, который основан на пакетах datatypes и dbi. Эта ограниченная реализация сосредоточена на функциональности запросов/курсов и обычно не поддерживает DDL и ORM операции SQLAlchemy. (SQLAlchemy ориентирован на OLTP базы данных, и мы рекомендуем использовать более специализированные инструменты и фреймворки для управления OLAP-ориентированной базой данных ClickHouse.)
  • Основной драйвер и реализация ClickHouse Connect SQLAlchemy являются предпочтительными методами для подключения ClickHouse к Apache Superset. Используйте строку подключения к базе данных ClickHouse Connect или clickhousedb диалекта SQLAlchemy.

Эта документация актуальна по состоянию на бета-версию 0.8.2.

примечание

Официальный драйвер Python ClickHouse Connect использует HTTP-протокол для связи с сервером ClickHouse. Он имеет некоторые преимущества (такие как лучшая гибкость, поддержка HTTP-балансировщиков, лучшее взаимодействие с инструментами на основе JDBC и др.) и недостатки (такие как немного более низкое сжатие и производительность, а также отсутствие поддержки некоторых сложных функций родного протокола на основе TCP). Для некоторых случаев использования вы можете рассмотреть возможность использования одного из сообществ драйверов Python, который использует родной протокол на основе TCP.

Требования и совместимость

PythonПлатформа¹ClickHouseSQLAlchemy²Apache Superset
2.x, <3.8Linux (x86)<24.3³🟡<1.3<1.4
3.8.xLinux (Aarch64)24.3.x1.3.x1.4.x
3.9.xmacOS (x86)24.4-24.6³🟡1.4.x1.5.x
3.10.xmacOS (ARM)24.7.x>=2.x2.0.x
3.11.xWindows24.8.x2.1.x
3.12.x24.9.x3.0.x

¹ClickHouse Connect был явно протестирован на указанных платформах. В дополнение к этому, неподтвержденные двоичные колеса (с оптимизацией C) создаются для всех архитектур, поддерживаемых отличным проектом cibuildwheel. Наконец, поскольку ClickHouse Connect также может работать как чистый Python, установка из исходников должна работать на любой недавней установке Python.

²Поддержка SQLAlchemy ограничена преимущественно функциональностью запросов. Полный API SQLAlchemy не поддерживается.

³ClickHouse Connect был протестирован на всех активно поддерживаемых версиях ClickHouse. Поскольку он использует HTTP-протокол, он также должен работать корректно для большинства других версий ClickHouse, хотя могут быть некоторые несовместимости с определенными расширенными типами данных.

Установка

Установите ClickHouse Connect из PyPI с помощью pip:

pip install clickhouse-connect

ClickHouse Connect также можно установить из исходников:

  • git clone репозиторий GitHub.
  • (По желанию) выполните pip install cython, чтобы собрать и включить оптимизации C/Cython.
  • Перейдите в корневую директорию проекта и выполните pip install .

Политика поддержки

ClickHouse Connect в настоящее время находится в бета-версии, и только текущая бета-версия активно поддерживается. Пожалуйста, обновитесь до последней версии перед подачей каких-либо проблем. Проблемы должны быть зарегистрированы в GitHub проекте. Будущие релизы ClickHouse Connect гарантированно будут совместимы с активно поддерживаемыми версиями ClickHouse на момент релиза (обычно три самых последних stable и две самых последних lts версии).

Основное использование

Подготовьте свои данные для подключения

Чтобы подключиться к ClickHouse с помощью HTTP(S), вам необходима следующая информация:

  • ХОСТ и ПОРТ: как правило, порт 8443 при использовании TLS или 8123 при отсутствии TLS.

  • ИМЯ БАЗЫ ДАННЫХ: по умолчанию существует база данных с именем default, используйте имя базы данных, к которой вы хотите подключиться.

  • ИМЯ ПОЛЬЗОВАТЕЛЯ и ПАРОЛЬ: по умолчанию имя пользователя default. Используйте имя пользователя, подходящее для вашего случая.

Данные для вашего сервиса ClickHouse Cloud доступны в консоли ClickHouse Cloud. Выберите сервис, к которому вы хотите подключиться, и нажмите Подключиться:

Кнопка подключения к сервису ClickHouse Cloud

Выберите HTTPS, и данные будут доступны в примере команды curl.

Детали подключения ClickHouse Cloud по HTTPS

Если вы используете самоуправляемый ClickHouse, детали подключения устанавливаются вашим администратором ClickHouse.

Установите соединение

Есть два примера подключения к ClickHouse:

  • Подключение к серверу ClickHouse на localhost.
  • Подключение к облачному сервису ClickHouse.
Используйте экземпляр клиента ClickHouse Connect для подключения к серверу ClickHouse на localhost:
import clickhouse_connect

client = clickhouse_connect.get_client(host='localhost', username='default', password='password')
Используйте экземпляр клиента ClickHouse Connect для подключения к облачному сервису ClickHouse:
подсказка

Используйте данные подключения, собранные ранее. Сервисы облака ClickHouse требуют TLS, поэтому используйте порт 8443.

import clickhouse_connect

client = clickhouse_connect.get_client(host='HOSTNAME.clickhouse.cloud', port=8443, username='default', password='your password')

Взаимодействуйте с вашей базой данных

Чтобы выполнить SQL-команду ClickHouse, используйте метод command клиента:

client.command('CREATE TABLE new_table (key UInt32, value String, metric Float64) ENGINE MergeTree ORDER BY key')

Чтобы вставить пакет данных, используйте метод insert клиента с двумерным массивом строк и значений:

row1 = [1000, 'String Value 1000', 5.233]
row2 = [2000, 'String Value 2000', -107.04]
data = [row1, row2]
client.insert('new_table', data, column_names=['key', 'value', 'metric'])

Чтобы получить данные с помощью SQL ClickHouse, используйте метод query клиента:

result = client.query('SELECT max(key), avg(metric) FROM new_table')
result.result_rows
Out[13]: [(2000, -50.9035)]

API драйвера ClickHouse Connect

Примечание: Рекомендуется передавать аргументы по ключам для большинства API-методов, учитывая количество возможных аргументов, большинство из которых являются необязательными.

Методы, не задокументированные здесь, не считаются частью API и могут быть удалены или изменены.

Инициализация клиента

Класс clickhouse_connect.driver.client предоставляет основной интерфейс между приложением Python и сервером базы данных ClickHouse. Используйте функцию clickhouse_connect.get_client, чтобы получить экземпляр Client, который принимает следующие аргументы:

Аргументы подключения

ПараметрТипПо умолчаниюОписание
interfacestrhttpДолжен быть установлен в http или https.
hoststrlocalhostИмя хоста или IP-адрес сервера ClickHouse. Если не установлено, будет использовано значение localhost.
portint8123 или 8443Порт ClickHouse HTTP или HTTPS. Если не установлен, по умолчанию используется 8123 или 8443, если secure=True или interface=https.
usernamestrdefaultИмя пользователя ClickHouse. Если не установлено, будет использован пользователь ClickHouse по умолчанию default.
passwordstr<пустая строка>Пароль для username.
databasestrNoneБаза данных по умолчанию для соединения. Если не установлено, ClickHouse Connect будет использовать базу данных по умолчанию для username.
secureboolFalseИспользовать https/TLS. Это переопределяет выводимые значения из аргументов интерфейса или порта.
dsnstrNoneСтрока в стандартном формате DSN (Data Source Name). Другие значения соединения (такие как хост или пользователь) будут извлечены из этой строки, если не установлены иным образом.
compressbool или strTrueВключить сжатие для HTTP вставок ClickHouse и результатов запросов. См. Дополнительные параметры (Сжатие)
query_limitint0 (без ограничений)Максимальное количество строк, которые следует вернуть для любого ответа на query. Установите это значение в ноль, чтобы вернуть неограниченное количество строк. Обратите внимание, что большие лимиты запросов могут привести к исключениям нехватки памяти, если результаты не передаются по потокам, так как все результаты загружаются в память сразу.
query_retriesint2Максимальное количество повторных попыток для запроса query. Только "повторяемые" HTTP-ответы будут повторены. Запросы command или insert не повторяются автоматически драйвером, чтобы предотвратить непреднамеренные повторные запросы.
connect_timeoutint10Таймаут подключения HTTP в секундах.
send_receive_timeoutint300Таймаут отправки/получения для HTTP-соединения в секундах.
client_namestrNoneclient_name, добавленное к заголовку HTTP User Agent. Установите это значение, чтобы отслеживать клиентские запросы в системном журнале ClickHouse.
pool_mgrobj<менеджер пула по умолчанию>Менеджер пула urllib3, который нужно использовать. Для более сложных случаев использования, требующих нескольких пулов соединения для разных хостов.
http_proxystrNoneАдрес HTTP-прокси (эквивалентно установке переменной окружения HTTP_PROXY).
https_proxystrNoneАдрес HTTPS-прокси (эквивалентно установке переменной окружения HTTPS_PROXY).
apply_server_timezoneboolTrueИспользовать серверный часовой пояс для учитываемых запросов с результатами. См. Приоритет часовых поясов

Аргументы HTTPS/TLS

ПараметрТипПо умолчаниюОписание
verifyboolTrueПроверить сертификат TLS/SSL сервера ClickHouse (имя хоста, срок действия и т.д.) при использовании HTTPS/TLS.
ca_certstrNoneЕсли verify=True, путь к файлу корневого сертификата Центра сертификации для проверки сертификата сервера ClickHouse в формате .pem. Игнорируется, если verify равно False. Это не обязательно, если сертификат сервера ClickHouse является глобально доверенным корнем, как это подтверждается операционной системой.
client_certstrNoneПуть к файлу клиентского сертификата TLS в формате .pem (для взаимной аутентификации TLS). Файл должен содержать полный цепь сертификатов, включая любые промежуточные сертификаты.
client_cert_keystrNoneПуть к закрытому ключу для клиентского сертификата. Требуется, если закрытый ключ не включен в файл ключа клиентского сертификата.
server_host_namestrNoneИмя хоста сервера ClickHouse, определенное CN или SNI его сертификата TLS. Установите это, чтобы избежать ошибок SSL при подключении через прокси или туннель с другим именем хоста
tls_modestrNoneУправляет расширенным поведением TLS. proxy и strict не вызывают взаимное TLS соединение ClickHouse, но отправляют клиентский сертификат и ключ. mutual предполагает взаимную аутентификацию TLS ClickHouse с клиентским сертификатом. Переопределение значений None/по умолчанию — это mutual

Аргументы настроек

Наконец, аргумент settings для get_client используется для передачи дополнительных настроек ClickHouse серверу для каждого запроса клиента. Обратите внимание, что в большинстве случаев пользователи с доступом readonly=1 не могут изменять настройки, отправленные с запросом, поэтому ClickHouse Connect удалит такие настройки в окончательном запросе и запишет предупреждение. Следующие настройки применяются только к HTTP запросам/сессиям, используемым ClickHouse Connect, и не документируются как общие настройки ClickHouse.

НастройкаОписание
buffer_sizeРазмер буфера (в байтах), используемый сервером ClickHouse перед записью в HTTP-канал.
session_idУникальный идентификатор сессии для ассоциации связанных запросов на сервере. Обязателен для временных таблиц.
compressДолжен ли сервер ClickHouse сжимать данные ответа POST. Это значение следует использовать только для "сырьевых" запросов.
decompressНужно ли данные, отправленные на сервер ClickHouse, разжать. Эта настройка должна использоваться только для "сырьевых" вставок.
quota_keyКлюч квоты, связанный с этим запросом. См. документацию по квотам сервера ClickHouse.
session_checkИспользуется для проверки статуса сессии.
session_timeoutКоличество секунд бездействия, после которого идентификатор сессии станет недействительным. По умолчанию 60 секунд.
wait_end_of_queryБуферизует весь ответ на сервере ClickHouse. Эта настройка необходима для возврата итоговой информации и автоматически устанавливается для непотоковых запросов.

Для других настроек ClickHouse, которые могут быть отправлены с каждым запросом, смотрите документацию ClickHouse.

Примеры создания клиента

  • Без каких-либо параметров клиент ClickHouse Connect подключится к порту HTTP по умолчанию на localhost с пользователем по умолчанию и без пароля:
import clickhouse_connect

client = clickhouse_connect.get_client()
client.server_version
Out[2]: '22.10.1.98'
  • Подключение к безопасному (https) внешнему серверу ClickHouse
import clickhouse_connect

client = clickhouse_connect.get_client(host='play.clickhouse.com', secure=True, port=443, user='play', password='clickhouse')
client.command('SELECT timezone()')
Out[2]: 'Etc/UTC'
  • Подключение с идентификатором сеанса и другими пользовательскими параметрами подключения и настройками ClickHouse.
import clickhouse_connect

client = clickhouse_connect.get_client(host='play.clickhouse.com',
                                       user='play',
                                       password='clickhouse',
                                       port=443,
                                       session_id='example_session_1',
                                       connect_timeout=15,
                                       database='github',
                                       settings={'distributed_ddl_task_timeout':300})
client.database
Out[2]: 'github'

Общие аргументы методов

Несколько методов клиента используют один или оба общих аргумента parameters и settings. Эти аргументы по ключам описаны ниже.

Аргумент параметров

Методы ClickHouse Connect Client query* и command принимают необязательный аргумент ключевого слова parameters, используемый для связывания выражений Python с выражением значения ClickHouse. Доступно два типа связывания.

Связывание на стороне сервера

ClickHouse поддерживает связь на стороне сервера для большинства значений запросов, где связываемое значение отправляется отдельно от запроса как параметр HTTP-запроса. ClickHouse Connect добавит соответствующие параметры запроса, если обнаружит выражение связывания формы {<name>:<datatype>}. Для связывания на стороне сервера аргумент parameters должен быть словарем Python.

  • Связь на стороне сервера с использованием словаря Python, значения DateTime и строкового значения
import datetime

my_date = datetime.datetime(2022, 10, 1, 15, 20, 5)

parameters = {'table': 'my_table', 'v1': my_date, 'v2': "a string with a single quote'"}
client.query('SELECT * FROM {table:Identifier} WHERE date >= {v1:DateTime} AND string ILIKE {v2:String}', parameters=parameters)


# Generates the following query on the server

# SELECT * FROM my_table WHERE date >= '2022-10-01 15:20:05' AND string ILIKE 'a string with a single quote\''

ВАЖНО — Связывание на стороне сервера поддерживается (сервером ClickHouse) только для запросов SELECT. Оно не работает для запросов ALTER, DELETE, INSERT или других типов запросов. Это может измениться в будущем, смотрите https://github.com/ClickHouse/ClickHouse/issues/42092.

Связывание на стороне клиента

ClickHouse Connect также поддерживает связывание параметров на стороне клиента, что может предоставить большую гибкость в генерации шаблонных SQL-запросов. Для связывания на стороне клиента аргумент parameters должен быть словарем или последовательностью. Связывание на стороне клиента использует форматирование строк Python в стиле "printf" для замены параметров.

Обратите внимание, что, в отличие от связывания на стороне сервера, связывание на стороне клиента не работает для идентификаторов базы данных, таких как название базы данных, таблиц или колонок, поскольку форматирование в стиле Python не может различать разные типы строк, и их нужно форматировать по-разному (обратные кавычки или двойные кавычки для идентификаторов базы данных, одинарные кавычки для значений данных).

  • Пример с использованием словаря Python, значения DateTime и экранирования строк
import datetime

my_date = datetime.datetime(2022, 10, 1, 15, 20, 5)

parameters = {'v1': my_date, 'v2': "a string with a single quote'"}
client.query('SELECT * FROM some_table WHERE date >= %(v1)s AND string ILIKE %(v2)s', parameters=parameters)


# Generates the following query:

# SELECT * FROM some_table WHERE date >= '2022-10-01 15:20:05' AND string ILIKE 'a string with a single quote\''
  • Пример с использованием базы данных Python (Tuple), Float64 и IPv4Address
import ipaddress

parameters = (35200.44, ipaddress.IPv4Address(0x443d04fe))
client.query('SELECT * FROM some_table WHERE metric >= %s AND ip_address = %s', parameters=parameters)


# Generates the following query:

# SELECT * FROM some_table WHERE metric >= 35200.44 AND ip_address = '68.61.4.254''
примечание

Для связывания аргументов DateTime64 (типы ClickHouse с точностью до субсекунд) требуется один из двух пользовательских подходов:

  • Обернуть значение Python datetime.datetime в новый класс DT64Param, например,
query = 'SELECT {p1:DateTime64(3)}'  # Server side binding with dictionary
parameters={'p1': DT64Param(dt_value)}

query = 'SELECT %s as string, toDateTime64(%s,6) as dateTime' # Client side binding with list 
parameters=['a string', DT64Param(datetime.now())]
  • Если используете словарь значений параметров, добавьте строку _64 к имени параметра
query = 'SELECT {p1:DateTime64(3)}, {a1:Array(DateTime(3))}'  # Server side binding with dictionary

parameters={'p1_64': dt_value, 'a1_64': [dt_value1, dt_value2]}

Аргумент настроек

Все ключевые методы клиента ClickHouse Connect "insert" и "select" принимают необязательный аргумент ключевого слова settings, чтобы передать настройки пользователя ClickHouse настройки для данного SQL-запроса. Аргумент settings должен быть словарем. Каждый элемент должен быть именем настройки ClickHouse и его соответствующим значением. Обратите внимание, что значения будут преобразованы в строки при отправке на сервер в качестве параметров запроса.

Как и для настроек уровня клиента, ClickHouse Connect удалит любые настройки, которые сервер помечает как readonly=1, с сообщением в журнале. Настройки, которые применяются только к запросам через HTTP-интерфейс ClickHouse, всегда действительны. Эти настройки описаны в API метода get_client.

Пример использования настроек ClickHouse:

settings = {'merge_tree_min_rows_for_concurrent_read': 65535,
            'session_id': 'session_1234',
            'use_skip_indexes': False}
client.query("SELECT event_type, sum(timeout) FROM event_errors WHERE event_time > '2022-08-01'", settings=settings)

Метод клиента command

Используйте метод Client.command, чтобы отправлять SQL-запросы на сервер ClickHouse, которые обычно не возвращают данные или возвращают одно простое значение или массив, а не полный набор данных. Этот метод принимает следующие параметры:

ПараметрТипПо умолчаниюОписание
cmdstrОбязательныйSQL-команда ClickHouse, которая возвращает единичное значение или одну строку значений.
parametersdict или iterableNoneСм. описание параметров.
datastr или bytesNoneДополнительные данные, которые необходимо включить с командой в качестве тела POST-запроса.
settingsdictNoneСм. описание настроек.
use_databaseboolTrueИспользовать клиентскую базу данных (указанную при создании клиента). Значение False означает, что команда будет использовать базу данных по умолчанию сервера ClickHouse для подключенного пользователя.
external_dataExternalDataNoneОбъект ExternalData, содержащий файлы или двоичные данные для использования с запросом. См. Расширенные запросы (Внешние данные)
  • command может быть использован для DDL операторов. Если SQL "command" не возвращает данные, возвращается вместо этого словарь "сводки запросов", который инкапсулирует заголовки ClickHouse X-ClickHouse-Summary и X-ClickHouse-Query-Id, включая пары ключ/значение written_rows, written_bytes и query_id.
client.command('CREATE TABLE test_command (col_1 String, col_2 DateTime) Engine MergeTree ORDER BY tuple()')
client.command('SHOW CREATE TABLE test_command')
Out[6]: 'CREATE TABLE default.test_command\\n(\\n    `col_1` String,\\n    `col_2` DateTime\\n)\\nENGINE = MergeTree\\nORDER BY tuple()\\nSETTINGS index_granularity = 8192'
  • command также может быть использован для простых запросов, которые возвращают только одну строку
result = client.command('SELECT count() FROM system.tables')
result
Out[7]: 110

Метод клиента query

Метод Client.query является основным способом получения одного "пакета" набора данных с сервера ClickHouse. Он использует родной формат ClickHouse через HTTP для эффективной передачи больших наборов данных (до approximately одного миллиона строк). Этот метод принимает следующие параметры.

ПараметрТипПо умолчаниюОписание
querystrОбязательныйЗапрос ClickHouse SQL SELECT или DESCRIBE.
parametersdict или iterableNoneСм. описание параметров.
settingsdictNoneСм. описание настроек.
query_formatsdictNoneСпецификация форматирования типов для значений результата. См. Расширенное использование (Чтение форматов)
column_formatsdictNoneФорматирование типов для каждой колонки. См. Расширенное использование (Чтение форматов)
encodingstrNoneКодировка, используемая для кодирования строковых колонок ClickHouse в строках Python. Python по умолчанию использует UTF-8, если не установлен.
use_noneboolTrueИспользовать тип Python None для ClickHouse null. Если False, использовать значение по умолчанию для типа данных (например, 0) для ClickHouse null. Обратите внимание, что для NumPy/Pandas по умолчанию значение False в целях повышения производительности.
column_orientedboolFalseВозвращать результаты как последовательность колонок, а не строк. Полезно для преобразования данных Python в другие форматы данных, ориентированные на колонки.
query_tzstrNoneНазвание часового пояса из базы данных zoneinfo. Этот часовой пояс будет применяться ко всем объектам datetime или Pandas Timestamp, возвращаемым запросом.
column_tzsdictNoneСловарь названия колонки на название часового пояса. Как query_tz, но позволяет задавать разные часовые пояса для разных колонок.
use_extended_dtypesboolTrueИспользовать расширенные типы данных Pandas (например, StringArray) и pandas.NA и pandas.NaT для значений NULL ClickHouse. Применяется только для методов query_df и query_df_stream.
external_dataExternalDataNoneОбъект ExternalData, содержащий файлы или двоичные данные для использования с запросом. См. Расширенные запросы (Внешние данные)
contextQueryContextNoneПовторно используемый объект QueryContext может использоваться для инкапсуляции вышеуказанных аргументов метода. См. Расширенные запросы (QueryContexts)

Объект QueryResult

Базовый метод query возвращает объект QueryResult со следующими публичными свойствами:

  • result_rows -- Матрица данных, возвращаемых в виде последовательности строк, где каждый элемент строки является последовательностью значений колонок.
  • result_columns -- Матрица данных, возвращаемых в виде последовательности колонок, где каждый элемент колонки является последовательностью значений строк для этой колонки.
  • column_names -- Кортеж строк, представляющий имена колонок в result_set.
  • column_types -- Кортеж экземпляров ClickHouseType, представляющих тип данных ClickHouse для каждой колонки в result_columns.
  • query_id -- Идентификатор запроса ClickHouse (полезен для изучения запроса в таблице system.query_log).
  • summary -- Любые данные, возвращаемые заголовком HTTP-ответа X-ClickHouse-Summary.
  • first_item -- Удобное свойство для получения первой строки ответа в виде словаря (ключи - имена колонок).
  • first_row -- Удобное свойство для возврата первой строки результата.
  • column_block_stream -- Генератор результатов запроса в формате колонок. Это свойство не должно использоваться напрямую (см. ниже).
  • row_block_stream -- Генератор результатов запроса в формате строк. Это свойство не должно использоваться напрямую (см. ниже).
  • rows_stream -- Генератор результатов запроса, который возвращает одну строку за вызов. Это свойство не должно использоваться напрямую (см. ниже).
  • summary -- Как описано в методе command, словарь информации о сводке, возвращаемой ClickHouse.

Свойства *_stream возвращают контекст Python, который может быть использован как итератор для возвращаемых данных. Они должны быть доступны косвенно с использованием методов клиента *_stream.

Полные подробности потоковой передачи результатов запроса (с использованием объектов StreamContext) изложены в Расширенные запросы (Потоковые запросы).

Потребление результатов запроса с помощью NumPy, Pandas или Arrow

Существует три специализированные версии основного метода query:

  • query_np -- Эта версия возвращает массив NumPy вместо QueryResult ClickHouse Connect.
  • query_df -- Эта версия возвращает DataFrame Pandas вместо QueryResult ClickHouse Connect.
  • query_arrow -- Эта версия возвращает таблицу PyArrow. Она использует формат ClickHouse Arrow напрямую, поэтому принимает только три аргумента, общие с основным методом query: query, parameters и settings. В дополнение есть дополнительный аргумент use_strings, который определяет, будет ли таблица Arrow преобразовывать типы строк ClickHouse в строки (если True) или в байты (если False).

Методы потокового запроса клиента

Клиент 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 -- Возвращает данные запроса в виде RecordBlocks PyArrow.

Каждый из этих методов возвращает объект ContextStream, который необходимо открыть с помощью оператора with, чтобы начать потребление потока. См. Расширенные запросы (Потоковые запросы) для подробностей и примеров.

Метод insert клиента

Для общего случая вставки нескольких записей в ClickHouse есть метод Client.insert. Он принимает следующие параметры:

ПараметрТипПо умолчаниюОписание
tablestrОбязательныйТаблица ClickHouse для вставки. Разрешено полное имя таблицы (включая базу данных).
dataПоследовательность ПоследовательностейОбязательныйМатрица данных для вставки, либо последовательность строк, каждая из которых является последовательностью значений колонок, либо последовательность колонок, каждая из которых является последовательностью значений строк.
column_namesПоследовательность str, или str'*'Список имен колонок для матрицы данных. Если используется '*', ClickHouse Connect выполнит "предварительный запрос", чтобы получить все имена колонок для таблицы.
databasestr''Целевая база данных для вставки. Если не указано, будет подразумеваться база данных клиента.
column_typesПоследовательность ClickHouseTypeNoneСписок экземпляров ClickHouseType. Если ни column_types, ни column_type_names не указаны, ClickHouse Connect выполнит "предварительный запрос", чтобы получить все типы колонок для таблицы.
column_type_namesПоследовательность имен типов ClickHouseNoneСписок имен типов данных ClickHouse. Если ни column_types, ни column_type_names не указаны, ClickHouse Connect выполнит "предварительный запрос", чтобы получить все типы колонок для таблицы.
column_orientedboolFalseЕсли True, аргумент data считается последовательностью колонок (и "поворот" не будет необходим для вставки данных). В противном случае data интерпретируется как последовательность строк.
settingsdictNoneСм. описание настроек.
insert_contextInsertContextNoneМожно использовать объект InsertContext, чтобы инкапсулировать аргументы вышеуказанного метода. См. Расширенные вставки (InsertContexts).

Этот метод возвращает словарь "сводки запроса", как описано в методе "command". Будет сгенерировано исключение, если вставка не удалась по какой-либо причине.

Существуют две специализированные версии основного метода insert:

  • insert_df -- Вместо Python последовательности последовательностей аргумент data требует df, который должен быть экземпляром DataFrame Pandas. ClickHouse Connect автоматически обрабатывает DataFrame как ресурс с колонной, поэтому параметр column_oriented не требуется и не доступен.
  • insert_arrow -- Вместо Python последовательности последовательностей аргумент data требует arrow_table. ClickHouse Connect передает таблицу Arrow без изменений на сервер ClickHouse для обработки, поэтому только аргументы database и settings доступны дополнительно к table и arrow_table.

Примечание: Массив NumPy является действительной последовательностью последовательностей и может использоваться в качестве аргумента data для основного метода insert, поэтому специализированный метод не требуется.

Вставки из файлов

clickhouse_connect.driver.tools включает метод insert_file, который позволяет вставлять данные непосредственно из файловой системы в существующую таблицу ClickHouse. Парсинг делегируется серверу ClickHouse. insert_file принимает следующие параметры:

ПараметрТипПо умолчаниюОписание
clientClientОбязательныйКлиент driver.Client, используемый для выполнения вставки
tablestrОбязательныйТаблица ClickHouse, в которую будет выполнена вставка. Полное имя таблицы (включая базу данных) разрешено.
file_pathstrОбязательныйПуть к файлу данных в корневой файловой системе
fmtstrCSV, CSVWithNamesФормат ввода ClickHouse для файла. Если column_names не предоставлены, предполагается, что используется CSVWithNames
column_namesПоследовательность strNoneСписок имен колонок в файле данных. Не требуется для форматов, которые включают имена колонок
databasestrNoneБаза данных таблицы. Игнорируется, если таблица полностью квалифицирована. Если не указана, вставка будет использовать базу данных клиента
settingsdictNoneСм. описание настроек.
compressionstrNoneПризнаваемый тип сжатия ClickHouse (zstd, lz4, gzip), используемый для заголовка Content-Encoding HTTP

Для файлов с неконсистентными данными или значениями даты/времени в необычном формате принято учитывать настройки, применимые к импорту данных (такие как input_format_allow_errors_num и 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})

Сохранение результатов запроса как файлов

Вы можете передавать файлы напрямую из ClickHouse в локальную файловую систему с помощью метода raw_stream. Например, если вы хотите сохранить результаты запроса в файле CSV, вы можете использовать следующий фрагмент кода:

import clickhouse_connect

if __name__ == '__main__':
    client = clickhouse_connect.get_client()
    query = 'SELECT number, toString(number) AS number_as_str FROM system.numbers LIMIT 5'
    fmt = 'CSVWithNames'  # or CSV, or CSVWithNamesAndTypes, or TabSeparated, etc.
    stream = client.raw_stream(query=query, fmt=fmt)
    with open("output.csv", "wb") as f:
        for chunk in stream:
            f.write(chunk)

Код выше создает файл output.csv со следующим содержимым:

"number","number_as_str"
0,"0"
1,"1"
2,"2"
3,"3"
4,"4"

Аналогично, вы могли бы сохранить данные в формате TabSeparated и других форматах. См. Форматы для входных и выходных данных для получения обзора всех доступных вариантов форматов.

Чистый API

Для случаев использования, которые не требуют преобразования между данными ClickHouse и нативными или сторонними типами данных и структурами, клиент ClickHouse Connect предоставляет два метода для непосредственного использования подключения ClickHouse.

Метод raw_query клиента

Метод Client.raw_query позволяет использовать HTTP-интерфейс запросов ClickHouse напрямую, используя подключение клиента. Возвращаемое значение является необработанным объектом bytes. Он предлагает удобную оболочку с привязкой параметров, обработкой ошибок, повторными попытками и управлением настройками с помощью минимального интерфейса:

ПараметрТипПо умолчаниюОписание
querystrОбязательныйЛюбой действительный запрос ClickHouse
parametersdict или итераторNoneСм. описание параметров.
settingsdictNoneСм. описание настроек.
fmtstrNoneФормат вывода ClickHouse для возвращаемых байтов. (ClickHouse использует TSV, если не указано)
use_databaseboolTrueИспользовать базу данных, назначенную клиенту clickhouse-connect, для контекста запроса
external_dataExternalDataNoneОбъект ExternalData, содержащий файл или двоичные данные для использования с запросом. См. Расширенные запросы (Внешние данные)

Ответственность за обработку возвращаемого объекта bytes лежит на вызывающем. Обратите внимание, что Client.query_arrow является просто тонкой оболочкой вокруг этого метода, использующей формат вывода ClickHouse Arrow.

Метод raw_stream клиента

Метод Client.raw_stream имеет такой же API, как и метод raw_query, но возвращает объект io.IOBase, который может быть использован как генератор/источник потока объектов bytes. В настоящее время он используется методом query_arrow_stream.

Метод raw_insert клиента

Метод Client.raw_insert позволяет напрямую вставлять объекты bytes или генераторы объектов bytes, используя подключение клиента. Поскольку он не обрабатывает загрузку вставляемых данных, он имеет высокую производительность. Метод предоставляет опции для указания настроек и формата вставки:

ПараметрТипПо умолчаниюОписание
tablestrОбязательныйЛибо простое, либо квалифицированное имя таблицы
column_namesПоследовательность[str]NoneИмена колонок для вставочного блока. Требуется, если параметр fmt не включает имена
insert_blockstr, bytes, Генератор[bytes], BinaryIOОбязательныйДанные для вставки. Строки будут закодированы с использованием кодирования клиента.
settingsdictNoneСм. описание настроек.

Ответственность за то, чтобы insert_block был в указанном формате и использовал указанный метод сжатия, лежит на вызывающем. ClickHouse Connect использует эти необработанные вставки для загрузки файлов и таблиц PyArrow, передавая парсинг на сервер ClickHouse.

Утилитные классы и функции

Следующие классы и функции также считаются частью "публичного" API clickhouse-connect и, как и классы и методы, задокументированные выше, стабильны в рамках минорных обновлений. Изменения, нарушающие совместимость, для этих классов и функций произойдут только с минорным (а не патчевым) релизом и будут доступны со статусом устаревания в течение как минимум одного минорного релиза.

Исключения

Все пользовательские исключения (включая те, которые определены в спецификации DB API 2.0) определены в модуле clickhouse_connect.driver.exceptions. Исключения, которые фактически обнаруживает драйвер, будут использовать один из этих типов.

Утилиты Clickhouse SQL

Функции и класс DT64Param в модуле clickhouse_connect.driver.binding могут использоваться для корректной постройки и экранирования запросов SQL ClickHouse. Аналогично, функции в модуле clickhouse_connect.driver.parser могут использоваться для парсинга имен типов данных ClickHouse.

Многопоточные, многопроцессорные и асинхронные/событийно-ориентированные случаи использования

ClickHouse Connect хорошо работает в многопоточных, многопроцессорных и асинхронных приложениях с управлением событийными циклами. Все обработка запросов и вставок происходит в одном потоке, поэтому операции, как правило, являются безопасными для потоков. (Параллельная обработка некоторых операций на низком уровне является возможным будущим улучшением, чтобы преодолеть производственные потери от одного потока, но даже в этом случае безопасность потоков будет поддерживаться).

Поскольку каждый запрос или вставка выполняется с сохранением состояния в своем собственном объекте QueryContext или InsertContext, соответственно, эти вспомогательные объекты не являются безопасными для потоков и не должны использоваться между несколькими потоками обработки. См. дополнительное обсуждение объектов контекста в следующих разделах.

Кроме того, в приложении, где одновременно выполняется два или более запросов и/или вставок, есть два дополнительных момента, которые следует учитывать. Первый - это "сессия" ClickHouse, связанная с запросом/вставкой, а второй - это пул соединений HTTP, используемый экземплярами клиента ClickHouse Connect.

Обертка Asyncclient

С версии 0.7.16 ClickHouse Connect предоставляет асинхронную обертку над обычным Client, так что клиент можно использовать в среде asyncio.

Для получения экземпляра AsyncClient вы можете использовать фабричную функцию get_async_client, которая принимает те же параметры, что и стандартный get_client:

import asyncio

import clickhouse_connect

async def main():
    client = await clickhouse_connect.get_async_client()
    result = await client.query("SELECT name FROM system.databases LIMIT 1")
    print(result.result_rows)

asyncio.run(main())

AsyncClient имеет те же методы с теми же параметрами, что и стандартный Client, но они являются сопрограммами, когда это применимо. Внутренние методы класса Client, которые выполняют операции ввода-вывода, обернуты в вызов run_in_executor.

Производительность при многопоточном выполнении улучшится при использовании обертки AsyncClient, так как потоки выполнения и GIL будут освобождены во время ожидания завершения операций ввода-вывода.

Примечание: в отличие от обычного Client, AsyncClient по умолчанию устанавливает autogenerate_session_id в значение False.

См. также: пример run_async.

Управление идентификаторами сессий ClickHouse

Каждый запрос ClickHouse выполняется в контексте "сессии" ClickHouse. Сессии в настоящее время используются для двух целей:

  • Чтобы ассоциировать конкретные настройки ClickHouse с несколькими запросами (см. настройки пользователя). Команда ClickHouse SET используется для изменения настроек в рамках пользовательской сессии.
  • Для отслеживания временных таблиц.

По умолчанию каждый запрос, выполняемый с экземпляром клиента ClickHouse Connect, использует один и тот же идентификатор сессии, чтобы обеспечить эту функциональность сессии. То есть команды SET и работа с временными таблицами будут выполняться как ожидалось при использовании одного клиента ClickHouse. Однако по замыслу сервер ClickHouse не позволяет выполнять параллельные запросы внутри одной сессии. В результате существует два варианта для приложения ClickHouse Connect, которое будет выполнять параллельные запросы.

  • Создавать отдельный экземпляр Client для каждого потока выполнения (потока, процесса или обработчика событий), который будет иметь свой собственный идентификатор сессии. Это, как правило, лучший подход, так как он сохраняет состояние сессии для каждого клиента.
  • Использовать уникальный идентификатор сессии для каждого запроса. Это позволяет избежать проблемы параллельной сессии в тех случаях, когда временные таблицы или общие настройки сессии не требуются. (Общие настройки также могут быть предоставлены при создании клиента, но они отправляются с каждым запросом и не связаны с сессией). Уникальный идентификатор сессии может быть добавлен в словарь settings для каждого запроса, или вы можете отключить общую настройку autogenerate_session_id:
from clickhouse_connect import common

common.set_setting('autogenerate_session_id', False)  # This should always be set before creating a client
client = clickhouse_connect.get_client(host='somehost.com', user='dbuser', password=1234)

В этом случае ClickHouse Connect не отправит никаких идентификаторов сессий, и сервер ClickHouse сгенерирует случайный идентификатор сессии. ВAgain, временные таблицы и настройки уровня сессий не будут доступны.

Настройка пула HTTP соединений

ClickHouse Connect использует пулы соединений urllib3 для обработки основного HTTP-запроса к серверу. По умолчанию все экземпляры клиентов используют один и тот же пул соединений, что достаточно для большинства случаев использования. Этот пул по умолчанию поддерживает до 8 подключений HTTP Keep Alive к каждому серверу ClickHouse, используемому приложением.

Для крупных многопоточных приложений могут быть подходящими отдельные пулы соединений. Индивидуальные пулы соединений могут быть предоставлены как аргумент ключевого слова pool_mgr для основной функции clickhouse_connect.get_client:

import clickhouse_connect
from clickhouse_connect.driver import httputil

big_pool_mgr = httputil.get_pool_manager(maxsize=16, num_pools=12)

client1 = clickhouse_connect.get_client(pool_mgr=big_pool_mgr)
client2 = clickhouse_connect.get_client(pool_mgr=big_pool_mgr)

Как показано в приведенном выше примере, клиенты могут совместно использовать менеджер пула, или для каждого клиента может быть создан отдельный менеджер пула. Для получения дополнительных сведений о доступных параметрах при создании PoolManager см. документацию urllib3.

Запрос данных с помощью ClickHouse Connect: Расширенное использование

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'

Обратите внимание, что QueryContexts не безопасны для потоков, но копию можно получить в многопоточной среде, вызвав метод QueryContext.updated_copy.

Потоковые запросы

Блоки данных

ClickHouse Connect обрабатывает все данные из основного метода query как поток блоков, получаемых от сервера ClickHouse. Эти блоки передаются в пользовательском формате "Native" от и к ClickHouse. "Блок" - это просто последовательность колонок бинарных данных, где каждая колонка содержит равное количество значений данных указанного типа. (Как столбцовая база данных, ClickHouse хранит эти данные в аналогичном виде.) Размер блока, возвращаемого запросом, регулируется двумя пользовательскими настройками, которые могут быть установлены на нескольких уровнях (профиль пользователя, пользователь, сессия или запрос). Они:

  • max_block_size -- Ограничение на размер блока в строках. По умолчанию 65536.
  • preferred_block_size_bytes -- Мягкое ограничение на размер блока в байтах. По умолчанию 1,000,0000.

Независимо от preferred_block_size_setting, каждый блок никогда не будет больше max_block_size строк. В зависимости от типа запроса фактические возвращаемые блоки могут иметь любой размер. Например, запросы к распределенной таблице, охватывающей множество шарда, могут содержать меньшие блоки, полученные непосредственно из каждого шарда.

При использовании одного из методов 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, который является комбинированным контекстом/generator 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:
            <do something with each row of Python trip data>

Обратите внимание, что попытка использовать StreamContext без оператора with вызовет ошибку. Использование контекста Python гарантирует, что поток (в данном случае, поток HTTP-ответа) будет корректно закрыт, даже если не все данные будут потреблены и/или во время обработки возникла ошибка. Также StreamContexts могут использоваться только один раз для потребления потока. Попытка использовать 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, возвращаемый массив NumPy также будет иметь только один тип данных и может быть изменен/перевернут, не изменяя его внутреннюю структуру.

Метод query_df_stream возвращает каждый блок ClickHouse в виде двумерного DataFrame Pandas. Вот пример, который показывает, что объект StreamContext может быть использован как контекст отложенного выполнения (но только один раз).

Наконец, метод query_arrow_stream возвращает результат, отформатированный в ArrowStream ClickHouse, как pyarrow.ipc.RecordBatchStreamReader, обернутый в StreamContext. Каждая итерация потока возвращает RecordBlock PyArrow.

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, query_np и query_df. (Методы raw_query и query_arrow не изменяют входящие данные из ClickHouse, поэтому контроль формата не применяется.) Например, если формат чтения для UUID изменяется с формата по умолчанию native на альтернативный формат string, запрос ClickHouse к колонке UUID будет возвращен как строковые значения (используя стандартный формат 8-4-4-4-12 RFC 1422), а не как объекты UUID Python.

Аргумент "тип данных" для любой функции форматирования может включать подстановочные знаки. Формат представляет собой одну строку в нижнем регистре.

Форматы чтения могут быть установлены на нескольких уровнях:

  • Глобально, с использованием методов, определенных в пакете clickhouse_connect.datatypes.format. Это будет управлять форматом конфигурированного типа данных для всех запросов.
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')
  • Для целого запроса, используя необязательный аргумент словаря query_formats. В этом случае любая колонка (или подколонка) заданного типа данных будет использовать заданный формат.

# Return any UUID column as a string
client.query('SELECT user_id, user_uuid, device_uuid from users', query_formats={'UUID': 'string'})
  • Для значений в конкретной колонке, используя необязательный аргумент словаря column_formats. Ключом является имя колонки, возвращаемой ClickHouse, и формат для колонки данных или вторичный словарь "формата" с именем типа ClickHouse и значением формата запроса. Этот вторичный словарь может использоваться для вложенных типов колонн, таких как кортежи или карты.

# 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'})

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

ClickHouse TypeNative Python TypeRead FormatsComments
Int[8-64], UInt[8-32]int-
UInt64intsignedSuperset в настоящее время не обрабатывает большие беззнаковые значения UInt64
[U]Int[128,256]intstringЗначения int в Pandas и NumPy достигают 64 бит, поэтому эти значения могут возвращаться в виде строк
Float32float-Все Python float имеют внутренний формат 64 бита
Float64float-
Decimaldecimal.Decimal-
StringstringbytesСтолбцы ClickHouse типа String не имеют встроенного кодирования, поэтому их также используют для бинарных данных переменной длины
FixedStringbytesstringFixedStrings представляют собой массивы байтов фиксированной длины, но иногда их обрабатывают как строки в Python
Enum[8,16]stringstring, intPython enum не принимает пустые строки, поэтому все enum отображаются как строки или как их базовое целочисленное значение.
Datedatetime.dateintClickHouse хранит даты как дни с 01/01/1970. Это значение доступно как int
Date32datetime.dateintТо же самое, что и для Date, но с более широким диапазоном дат
DateTimedatetime.datetimeintClickHouse хранит DateTime в эпохе в секундах. Это значение доступно как int
DateTime64datetime.datetimeintPython datetime.datetime ограничен точностью до микросекунд. Сырой 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. Эти двоичные данные отправляются вместе со строкой запроса для обработки данных. Подробности о функции Внешние Данные можно найти здесь. Методы клиента query* принимают необязательный параметр external_data, чтобы воспользоваться этой функцией. Значение для параметра external_data должно быть объектом clickhouse_connect.driver.external.ExternalData. Конструктор этого объекта принимает следующие аргументы:

NameTypeDescription
file_pathstrПуть к файлу на локальном пути системы для чтения внешних данных. Либо file_path, либо data обязательны
file_namestrИмя внешнего "файла". Если не предоставлено, будет определено по file_path (без расширений)
databytesВнешние данные в двоичном виде (вместо чтения из файла). Либо data, либо file_path обязательны
fmtstrВходной формат ClickHouse Input Format данных. По умолчанию 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.

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

Существует несколько механизмов для применения часового пояса к значениям DateTime и DateTime64 в ClickHouse. Внутренне сервер ClickHouse всегда хранит любой объект DateTime или DateTime64 как число, не зависящее от часового пояса, представляющее секунды с эпохи, 1970-01-01 00:00:00 UTC. Для значений DateTime64 такое представление может быть в миллисекундах, микросекундах или наносекундах с момента эпохи, в зависимости от точности. В результате применение любой информации о часовом поясе всегда происходит на стороне клиента. Обратите внимание, что это включает в себя значительные дополнительные вычисления, поэтому в приложениях, критичных к производительности, рекомендуется рассматривать типы DateTime как отметки времени эпохи, за исключением отображения для пользователя и преобразования (например, метки времени Pandas всегда являются 64-битным целым числом, представляющим эпоху в наносекундах для повышения производительности).

При использовании типов данных, учитывающих часовой пояс, в запросах - в частности, объекта datetime.datetime в Python -- clickhouse-connect применяет часовой пояс на стороне клиента, используя следующие правила приоритета:

  1. Если для метода запроса указан параметр client_tzs, применяется конкретный часовой пояс колонки
  2. Если колонка ClickHouse имеет метаданные о часовом поясе (т.е. это тип, такой как DateTime64(3, 'America/Denver')), применяется часовой пояс колонки ClickHouse. (Обратите внимание, что эти метаданные о часовом поясе недоступны для clickhouse-connect для колонок DateTime до версии ClickHouse 23.2)
  3. Если для метода запроса указан параметр query_tz, применяется "часовой пояс запроса".
  4. Если настройка часового пояса применяется к запросу или сессии, применяется этот часовой пояс. (Эта функциональность еще не выпущена в сервере ClickHouse)
  5. Наконец, если параметр клиента apply_server_timezone установлен в True (по умолчанию), применяется часовой пояс сервера ClickHouse.

Обратите внимание, что если примененный часовой пояс на основе этих правил - это UTC, clickhouse-connect всегда вернет объект Python datetime.datetime, не зависящий от часового пояса. Дополнительная информация о часовом поясе может быть добавлена к этому объекту, не зависящему от часового пояса, кодом приложения, если это необходимо.

Вставка данных с ClickHouse Connect: Расширенное использование

InsertContexts

ClickHouse Connect выполняет все вставки в рамках InsertContext. InsertContext включает все значения, отправленные в качестве аргументов методу клиента insert. Кроме того, когда InsertContext первоначально создается, ClickHouse Connect извлекает типы данных для столбцов вставки, необходимые для эффективных вставок в формате Native. Повторное использование InsertContext для нескольких вставок позволяет избежать этого "предварительного запроса", и вставки выполняются быстрее и эффективнее.

InsertContext можно получить с помощью метода клиента create_insert_context. Метод принимает те же аргументы, что и функция insert. Обратите внимание, что только свойство data InsertContexts должно изменяться для повторного использования. Это согласуется с его предполагаемым назначением предоставления повторно используемого объекта для многократных вставок новых данных в одну и ту же таблицу.

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 включают изменяемое состояние, которое обновляется в процессе вставки, поэтому они не являются безопасными для потоков.

Форматы записи

Форматы записи в настоящее время реализованы для ограниченного числа типов. В большинстве случаев ClickHouse Connect будет пытаться автоматически определить правильный формат записи для столбца, проверяя тип первого (не нулевого) значения данных. Например, если вставляется значение в столбец DateTime и первое значение вставки в столбец - целое число Python, ClickHouse Connect будет напрямую вставлять целочисленное значение, предполагая, что это значение действительно представляет секунду эпохи.

В большинстве случаев нет необходимости переопределять формат записи для типа данных, но соответствующие методы в пакете clickhouse_connect.datatypes.format могут быть использованы для этого на глобальном уровне.

Опции формата записи

ClickHouse TypeNative Python TypeWrite FormatsComments
Int[8-64], UInt[8-32]int-
UInt64int
[U]Int[128,256]int
Float32float
Float64float
Decimaldecimal.Decimal
Stringstring
FixedStringbytesstringЕсли вставить как строку, дополнительные байты будут установлены в ноль
Enum[8,16]string
Datedatetime.dateintClickHouse хранит даты как дни с 01/01/1970. Для типов int будет предполагаться, что это значение "даты эпохи"
Date32datetime.dateintТо же самое, что и для Date, но для более широкого диапазона дат
DateTimedatetime.datetimeintClickHouse хранит DateTime в эпохе в секундах. Для типов int будет предполагаться, что это значение "секунды эпохи"
DateTime64datetime.datetimeintPython datetime.datetime ограничен точностью до микросекунд. Сырой 64-битный int доступен
IPv4ipaddress.IPv4AddressstringКорректно отформатированные строки могут быть вставлены как IPv4 адреса
IPv6ipaddress.IPv6AddressstringКорректно отформатированные строки могут быть вставлены как IPv6 адреса
Tupledict or tuple
Mapdict
NestedSequence[dict]
UUIDuuid.UUIDstringКорректно отформатированные строки могут быть вставлены как UUID ClickHouse
JSON/Object('json')dictstringМожно вставлять как словари, так и JSON строки в JSON столбцы (обратите внимание, что Object('json') устарел)
VariantobjectВ настоящее время все варианты вставляются как строки и обрабатываются сервером ClickHouse
DynamicobjectВнимание -- в настоящее время любые вставки в динамическую колонку сохраняются как строка ClickHouse

Дополнительные опции

ClickHouse Connect предоставляет ряд дополнительных опций для продвинутых случаев использования.

Глобальные настройки

Существует небольшое количество настроек, которые глобально контролируют поведение ClickHouse Connect. Они доступны из верхнего уровня пакета common:

from clickhouse_connect import common

common.set_setting('autogenerate_session_id', False)
common.get_setting('invalid_setting_action')
'drop'
примечание

Эти общие настройки autogenerate_session_id, product_name и readonly всегда должны изменяться перед созданием клиента с помощью метода clickhouse_connect.get_client. Изменение этих настроек после создания клиента не влияет на поведение существующих клиентов.

В настоящее время определено десять глобальных настроек:

Setting NameDefaultOptionsDescription
autogenerate_session_idTrueTrue, FalseАвтоматически сгенерировать новый UUID(1) идентификатор сессии (если не предоставлен) для каждой клиентской сессии. Если идентификатор сессии не предоставлен (либо на уровне клиента, либо на уровне запроса), ClickHouse сгенерирует случайный внутренний идентификатор для каждого запроса
invalid_setting_action'error''drop', 'send', 'error'Действие, которое следует предпринять, когда предоставлена недействительная или только для чтения настройка (либо для клиентской сессии, либо для запроса). Если drop, настройка будет игнорироваться, если send, настройка будет отправлена в ClickHouse, если error будет вызвано исключение ProgrammingError на стороне клиента
dict_parameter_format'json''json', 'map'Это определяет, нужно ли параметризованные запросы преобразовывать словарь Python в JSON или синтаксис ClickHouse Map. json следует использовать для вставок в JSON столбцы, map для колонок ClickHouse Map
product_nameСтрока, которая передается вместе с запросом в ClickHouse для отслеживания приложения, использующего ClickHouse Connect. Должна быть в формате <product_name>/<product_version>
max_connection_age600Максимальное количество секунд, в течение которых соединение HTTP Keep Alive будет открыто / повторно использовано. Это предотвращает сгущение соединений к единственному узлу ClickHouse за балансировщиком нагрузки / прокси. По умолчанию 10 минут.
readonly00, 1Неявные настройки ClickHouse "read_only" для версий ниже 19.17. Могут быть установлены для соответствия значению ClickHouse "read_only" для настроек, чтобы разрешить работу с очень старыми версиями ClickHouse
use_protocol_versionTrueTrue, FalseИспользовать версию клиентского протокола. Это необходимо для колонок временных меток с учетом часовых поясов, но нарушает работу с текущей версией chproxy
max_error_size1024Максимальное количество символов, которые будут возвращены в сообщений об ошибках клиента. Установите 0 для этой настройки, чтобы получить полное сообщение об ошибке ClickHouse. По умолчанию 1024 символа.
send_os_userTrueTrue, FalseВключить обнаруживаемое имя пользователя операционной системы в информацию клиента, отправленную в ClickHouse (HTTP User-Agent строка)
http_buffer_size10MBРазмер (в байтах) "внутреннего" буфера, используемого для потоковых запросов HTTP

Сжатие

ClickHouse Connect поддерживает сжатие lz4, zstd, brotli и gzip как для результатов запросов, так и для вставок. Всегда имейте в виду, что использование сжатия обычно связано с компромиссом между пропускной способностью сети / скоростью передачи и использованием CPU (как на стороне клиента, так и на стороне сервера).

Чтобы получать сжатые данные, параметр сервера ClickHouse enable_http_compression должен быть установлен в 1, или у пользователя должен быть разрешение на изменение настройки на основе "каждого запроса".

Сжатие контролируется параметром compress при вызове фабричного метода clickhouse_connect.get_client. По умолчанию compress установлен в True, что вызовет использование настроек сжатия по умолчанию. Для запросов, выполненных с использованием методов клиента query, query_np и query_df, ClickHouse Connect добавит заголовок Accept-Encoding с кодировками lz4, zstd, br (brotli, если библиотека brotli установлена), gzip и deflate к запросам, выполненным с использованием метода клиента query (и косвенно для query_np и query_df). (Для большинства запросов сервер ClickHouse будет возвращать данные сжатые с помощью zstd.) Для вставок по умолчанию ClickHouse Connect будет сжимать блоки вставок с помощью сжатия lz4 и отправлять HTTP заголовок Content-Encoding: lz4.

Параметр compress в методе get_client также может быть установлен на конкретный метод сжатия, один из lz4, zstd, br или gzip. Этот метод будет использоваться как для вставок, так и для результатов запросов (если это поддерживается сервером ClickHouse). Необходимые библиотеки сжатия zstd и lz4 теперь устанавливаются по умолчанию с ClickHouse Connect. Если указан br/brotli, библиотека brotli должна быть установлена отдельно.

Обратите внимание, что методы клиента raw* не используют сжатие, указанное клиентской конфигурацией.

Мы также не рекомендуем использовать сжатие gzip, поскольку оно значительно медленнее, чем альтернативы как для сжатия, так и для разжатия данных.

Поддержка HTTP-прокси

ClickHouse Connect добавляет базовую поддержку HTTP-прокси с использованием библиотеки urllib3. Она распознает стандартные переменные среды HTTP_PROXY и HTTPS_PROXY. Обратите внимание, что использование этих переменных среды будет применяться ко всем клиентам, созданным с помощью метода clickhouse_connect.get_client. В качестве альтернативы, для конфигурации для каждого клиента вы можете использовать параметры http_proxy или https_proxy метода get_client. Для получения подробностей об реализации поддержки HTTP-прокси смотрите документацию urllib3.

Для использования прокси Socks вы можете отправить urllib3 SOCKSProxyManager в качестве аргумента pool_mgr в get_client. Обратите внимание, что это потребует установки библиотеки PySocks либо напрямую, либо с использованием опции [socks] для зависимости urllib3.

Устаревший тип данных JSON

Экспериментальный тип данных Object (или Object('json')) устарел и должен избегаться в производственной среде. ClickHouse Connect продолжает предоставлять ограниченную поддержку данного типа данных для обратной совместимости. Обратите внимание, что эта поддержка не включает запросы, которые должны возвращать "узловые" или "родительские" значения JSON в виде словарей или эквивалентно, и такие запросы приведут к исключению.

"Новые" типы данных Variant/Dynamic/JSON (экспериментальная функция)

Начиная с версии 0.8.0, clickhouse-connect предоставляет экспериментальную поддержку новых (также экспериментальных) типов ClickHouse: Variant, Dynamic и JSON.

Примечания по использованию

  • Данные JSON могут вставляться как словарь Python или как строка JSON, содержащая JSON-объект {}. Другие формы данных JSON не поддерживаются.
  • Запросы, использующие подколонки/пути для этих типов, вернут тип подколонки.
  • См. основную документацию ClickHouse для других примечаний по использованию.

Известные ограничения

  • Каждый из этих типов должен быть включен в настройках ClickHouse перед использованием.
  • Новый тип JSON доступен начиная с версии ClickHouse 24.8.
  • Из-за изменений внутреннего формата clickhouse-connect совместим только с типами Variant, начиная с версии ClickHouse 24.7.
  • Возвращаемые JSON-объекты будут возвращать только количество элементов, равное max_dynamic_paths (по умолчанию 1024). Это будет исправлено в будущих релизах.
  • Вставки в столбцы Dynamic всегда будут строковым представлением значения Python. Это будет исправлено в будущих релизах, как только https://github.com/ClickHouse/ClickHouse/issues/70395 будет исправлено.
  • Реализация новых типов еще не была оптимизирована в C-коде, поэтому производительность может быть несколько ниже, чем у более простых, установленных типов данных.