ClickHouse JS
Официальный JS‑клиент для подключения к ClickHouse. Клиент написан на TypeScript и предоставляет типы для публичного API клиента.
Не имеет внешних зависимостей, оптимизирован для максимальной производительности и протестирован с различными версиями и конфигурациями ClickHouse (on-premises: одиночный узел, кластер, а также ClickHouse Cloud).
Существует две разные версии клиента для разных сред:
@clickhouse/client- только для Node.js@clickhouse/client-web- браузеры (Chrome/Firefox), Cloudflare Workers
При использовании TypeScript убедитесь, что его версия не ниже 4.5, в которой доступен синтаксис inline import и export.
Исходный код клиента доступен в GitHub-репозитории ClickHouse-JS.
Требования к среде (Node.js)
Для запуска клиента в среде должен быть установлен Node.js. Клиент совместим со всеми поддерживаемыми релизами Node.js.
Как только версия Node.js приближается к окончанию срока поддержки (End-Of-Life), клиент прекращает её поддержку, так как такая версия считается устаревшей и небезопасной.
Текущие поддерживаемые версии Node.js:
| Версия Node.js | Поддерживается? |
|---|---|
| 22.x | ✔ |
| 20.x | ✔ |
| 18.x | ✔ |
| 16.x | По возможности |
Требования к среде (веб)
Веб-версия клиента официально тестируется в последних версиях браузеров Chrome и Firefox и может использоваться как зависимость, например, в приложениях на React/Vue/Angular или в среде Cloudflare Workers.
Установка
Чтобы установить последнюю стабильную версию клиента Node.js, выполните следующую команду:
Установка веб-версии:
Совместимость с ClickHouse
| Версия клиента | ClickHouse |
|---|---|
| 1.12.0 | 24.8+ |
Вероятно, клиент будет работать и с более старыми версиями, однако такая поддержка предоставляется по принципу best-effort и не гарантируется. Если у вас версия ClickHouse ниже 23.3, обратитесь к политике безопасности ClickHouse и рассмотрите возможность обновления.
Примеры
Мы стремимся охватить различные сценарии использования клиента с помощью примеров в репозитории клиента.
Обзор доступен в README с примерами.
Если что-то остаётся непонятным или чего-то не хватает в примерах или в документации ниже, вы можете связаться с нами.
Клиентский API
Большинство примеров подходят как для Node.js, так и для веб-версии клиента, если явно не указано иное.
Создание экземпляра клиента
Вы можете создать столько экземпляров клиента, сколько необходимо, с помощью фабричной функции createClient:
Если ваша среда не поддерживает модули ESM, вместо этого вы можете использовать синтаксис CJS:
Экземпляр клиента можно заранее настроить при создании.
Конфигурация
При создании экземпляра клиента можно настроить следующие параметры подключения:
| Setting | Description | Default Value | See Also |
|---|---|---|---|
| url?: string | URL экземпляра ClickHouse. | http://localhost:8123 | Документация по конфигурации URL |
| pathname?: string | Необязательный pathname, добавляемый к URL ClickHouse после его разбора клиентом. | '' | Документация по прокси с pathname |
| request_timeout?: number | Таймаут запроса в миллисекундах. | 30_000 | - |
compression?: { **response**?: boolean; **request**?: boolean } | Включение сжатия. | - | Документация по сжатию |
| username?: string | Имя пользователя, от имени которого выполняются запросы. | default | - |
| password?: string | Пароль пользователя. | '' | - |
| application?: string | Имя приложения, использующего клиент Node.js. | clickhouse-js | - |
| database?: string | Имя используемой базы данных. | default | - |
| clickhouse_settings?: ClickHouseSettings | Настройки ClickHouse, применяемые ко всем запросам. | {} | - |
log?: { **LoggerClass**?: Logger, **level**?: ClickHouseLogLevel } | Конфигурация внутреннего логирования клиента. | - | Документация по логированию |
| session_id?: string | Необязательный идентификатор сессии ClickHouse, отправляемый с каждым запросом. | - | - |
keep_alive?: { **enabled**?: boolean } | По умолчанию включено как в версии для Node.js, так и в веб-версии. | - | - |
http_headers?: Record<string, string> | Дополнительные HTTP-заголовки для исходящих запросов в ClickHouse. | - | Документация по reverse proxy с аутентификацией |
| roles?: string | string[] | Имя или имена ролей ClickHouse, которые будут добавлены к исходящим запросам. | - | Использование ролей с HTTP-интерфейсом |
Параметры конфигурации, специфичные для Node.js
| Setting | Description | Default Value | See Also |
|---|---|---|---|
| max_open_connections?: number | Максимально допустимое количество подключённых сокетов для каждого хоста. | 10 | - |
tls?: { **ca_cert**: Buffer, **cert**?: Buffer, **key**?: Buffer } | Настройка сертификатов TLS. | - | Документация по TLS |
keep_alive?: { **enabled**?: boolean, **idle_socket_ttl**?: number } | - | - | Документация по Keep Alive |
| http_agent?: http.Agent | https.Agent Experimental feature. Learn more. | Пользовательский HTTP-агент для клиента. | - | Документация по HTTP-агенту |
| set_basic_auth_header?: boolean Experimental feature. Learn more. | Устанавливать заголовок Authorization с учетными данными basic auth. | true | Использование этого параметра в документации по HTTP-агенту |
Настройка URL
Настройка URL всегда переопределяет жестко заданные значения, и в этом случае в журнал будет записано предупреждение.
Большинство параметров экземпляра клиента можно настроить с помощью URL. Формат URL: http[s]://[username:password@]hostname:port[/database][?param1=value1¶m2=value2]. Почти во всех случаях имя конкретного параметра отражает его путь в интерфейсе параметров конфигурации, за несколькими исключениями. Поддерживаются следующие параметры:
| Параметр | Тип |
|---|---|
pathname | произвольная строка. |
application_id | произвольная строка. |
session_id | произвольная строка. |
request_timeout | неотрицательное число. |
max_open_connections | неотрицательное число, больше нуля. |
compression_request | логическое значение. См. ниже (1) |
compression_response | логическое значение. |
log_level | допустимые значения: OFF, TRACE, DEBUG, INFO, WARN, ERROR. |
keep_alive_enabled | логическое значение. |
clickhouse_setting_* or ch_* | см. ниже (2) |
http_header_* | см. ниже (3) |
(только для Node.js) keep_alive_idle_socket_ttl | неотрицательное число. |
- (1) Для логических параметров допустимыми являются значения
true/1иfalse/0. - (2) У любого параметра с префиксом
clickhouse_setting_илиch_этот префикс будет удален, а оставшаяся часть имени будет добавлена вclickhouse_settingsклиента. Например,?ch_async_insert=1&ch_wait_for_async_insert=1будет эквивалентен:
Примечание: логические значения параметра clickhouse_settings должны передаваться как 1/0 в URL.
- (3) Аналогично пункту (2), но для конфигурации
http_header. Например,?http_header_x-clickhouse-auth=foobarбудет эквивалентом:
Подключение
Соберите сведения о подключении
Чтобы подключиться к ClickHouse по HTTP(S), вам потребуется следующая информация:
| Параметр(ы) | Описание |
|---|---|
HOST и PORT | Обычно используется порт 8443 при использовании TLS или 8123 при отсутствии TLS. |
DATABASE NAME | По умолчанию существует база данных default; используйте имя базы данных, к которой вы хотите подключиться. |
USERNAME и PASSWORD | По умолчанию имя пользователя — default. Используйте имя пользователя, соответствующее вашему сценарию. |
Сведения о вашем сервисе ClickHouse Cloud доступны в консоли ClickHouse Cloud. Выберите сервис и нажмите Connect:

Выберите HTTPS. Параметры подключения отображаются в примере команды curl.

Если вы используете самостоятельное (self-managed) развертывание ClickHouse, параметры подключения задаются администратором ClickHouse.
Обзор подключения
Клиент устанавливает подключение по протоколу HTTP(s). Поддержка RowBinary находится в разработке, см. соответствующую задачу.
Следующий пример демонстрирует, как настроить подключение к ClickHouse Cloud. Предполагается, что значения url (включая
протокол и порт) и password заданы через переменные окружения, и используется пользователь default.
Пример: создание экземпляра клиента Node.js с использованием переменных окружения для настройки.
Репозиторий клиента содержит множество примеров, которые используют переменные окружения, например создание таблицы в ClickHouse Cloud, использование асинхронных вставок и многие другие.
Пул соединений (только Node.js)
Чтобы избежать накладных расходов на установку соединения при каждом запросе, клиент создает пул соединений с ClickHouse для их повторного использования, используя механизм Keep-Alive. По умолчанию Keep-Alive включен, а размер пула соединений равен 10, но вы можете изменить его с помощью параметра конфигурации max_open_connections параметра конфигурации.
Нет гарантии, что одно и то же соединение из пула будет использоваться для последующих запросов, если только пользователь не установит max_open_connections: 1. Это требуется редко, но может быть необходимо в случаях, когда используются временные таблицы.
См. также: Конфигурация Keep-Alive.
Идентификатор запроса
Каждый метод, который отправляет запрос или оператор (command, exec, insert, select), возвращает query_id в результате выполнения. Этот уникальный идентификатор назначается клиентом для каждого запроса и может быть полезен для выборки данных из system.query_log,
если он включён в конфигурации сервера, или для отмены долгих запросов (см. пример). При необходимости query_id может быть переопределён пользователем в параметрах методов command/query/exec/insert.
Если вы переопределяете параметр query_id, необходимо обеспечить его уникальность для каждого вызова. Хорошим вариантом будет случайный UUID.
Общие параметры для всех клиентских методов
Существует несколько параметров, которые могут быть применены ко всем клиентским методам (query/command/insert/exec).
Метод query
Используется для большинства запросов, которые могут вернуть ответ, таких как SELECT, а также для отправки DDL, таких как CREATE TABLE, и должен вызываться с await. Ожидается, что возвращённый результирующий набор данных будет использоваться в приложении.
См. также: Базовые параметры для всех клиентских методов.
Не указывайте клаузу FORMAT в query, вместо этого используйте параметр format.
Абстракции набора результатов и строк
ResultSet предоставляет несколько вспомогательных методов для обработки данных в вашем приложении.
Реализация ResultSet в Node.js внутренне использует Stream.Readable, тогда как веб-версия использует Web API ReadableStream.
Вы можете считывать данные из ResultSet, вызывая методы text или json у ResultSet и загружая в память весь набор строк, возвращаемый запросом.
Следует начать чтение ResultSet как можно раньше, так как он удерживает открытым поток ответа и, как следствие, держит занятым соответствующее соединение. Клиент не буферизует входящие данные, чтобы избежать потенциально чрезмерного использования памяти приложением.
Если набор данных слишком велик, чтобы поместиться в памяти целиком, вы можете вызвать метод stream и обрабатывать данные в потоковом режиме. В этом случае каждый из фрагментов ответа будет преобразован в относительно небольшой массив строк (размер этого массива зависит от размера конкретного фрагмента, который клиент получает от сервера, так как он может различаться, и от размера отдельной строки), обрабатываемый по одному фрагменту за раз.
Обратитесь к списку поддерживаемых форматов данных, чтобы определить, какой формат лучше подходит для потоковой обработки в вашем случае. Например, если вы хотите передавать в потоке JSON-объекты, вы можете выбрать формат JSONEachRow, и каждая строка будет разобрана как JS-объект, или, возможно, более компактный формат JSONCompactColumns, при котором каждая строка будет представлять собой компактный массив значений. См. также: потоковая передача файлов.
Если ResultSet или его поток не будут полностью прочитаны, они будут уничтожены по истечении периода бездействия, задаваемого request_timeout.
Пример: (Node.js/Web) Запрос с результирующим набором данных в формате JSONEachRow, который полностью считывает поток и разбирает содержимое в объекты JavaScript.
Исходный код.
Пример: (только для Node.js) потоковое чтение результата запроса в формате JSONEachRow с использованием классического подхода on('data'). Этот подход взаимозаменяем с синтаксисом for await const. Исходный код.
Пример: (только Node.js) Потоковая выборка результата запроса в формате CSV с использованием классического подхода on('data'). Это эквивалентно использованию синтаксиса for await const.
Исходный код
Пример: (только Node.js) Потоковая выборка результатов запроса как объекты JS в формате JSONEachRow, которые обрабатываются с использованием синтаксиса for await const. Это взаимозаменяемо с классическим подходом on('data').
Исходный код.
Синтаксис for await const требует немного меньше кода, чем подход с on('data'), но может отрицательно повлиять на производительность.
См. это обсуждение в репозитории Node.js для подробностей.
Пример: (только Web) Итерация по ReadableStream объектов.
Метод INSERT
Это основной метод вставки данных.
Тип возвращаемого значения минималистичен, так как мы не ожидаем, что сервер вернёт какие‑либо данные, и сразу же вычитываем и закрываем поток ответа.
Если в метод insert был передан пустой массив, оператор INSERT не будет отправлен на сервер; вместо этого метод немедленно вернёт результат { query_id: '...', executed: false }. Если в этом случае query_id не был передан в параметрах метода, в результате он будет пустой строкой, поскольку возврат случайного UUID, сгенерированного на стороне клиента, может ввести в заблуждение, так как запроса с таким query_id не будет в таблице system.query_log.
Если оператор INSERT был отправлен на сервер, флаг executed будет иметь значение true.
Метод insert и потоковая передача данных в Node.js
Он может работать как с Stream.Readable, так и с обычным Array<T>, в зависимости от формата данных, указанного для метода insert. См. также раздел о потоковой передаче файлов.
Метод insert предназначен для использования с await; однако можно передать входной поток и ожидать завершения операции insert позже, только после завершения потока (что также приведёт к разрешению промиса insert). Это потенциально может быть полезно для обработчиков событий и подобных сценариев, но обработка ошибок при этом может оказаться нетривиальной из‑за большого количества крайних случаев на стороне клиента. Вместо этого рассмотрите использование асинхронных вставок, как показано в этом примере.
Если у вас есть собственный оператор INSERT, который сложно смоделировать с помощью этого метода, рассмотрите использование метода command.
Вы можете посмотреть, как он используется, в примерах INSERT INTO ... VALUES или INSERT INTO ... SELECT.
См. также: Базовые параметры для всех клиентских методов.
Отмена запроса с помощью abort_signal не гарантирует, что вставка данных не была выполнена, так как сервер мог получить часть передаваемых по потоку данных до момента отмены.
Пример: (Node.js/Web) Вставка массива значений. Исходный код.
Пример: (только Node.js) Вставка потока из CSV‑файла. Исходный код. См. также: потоковая передача файлов.
Пример: исключение отдельных столбцов из оператора INSERT.
Пусть имеется определение таблицы следующего вида:
Вставить только один столбец:
Исключить некоторые столбцы:
См. исходный код для получения дополнительных сведений.
Пример: Вставка в другую базу данных, а не ту, что указана в экземпляре клиента. Исходный код.
Ограничения веб-версии
В настоящий момент операции вставки в @clickhouse/client-web работают только с форматами Array<T> и JSON*.
Вставка потоков пока не поддерживается в веб-версии из-за ограниченной поддержки в браузерах.
Соответственно, интерфейс InsertParams для веб-версии выглядит немного иначе, чем в версии для Node.js,
так как values ограничены только типом ReadonlyArray<T>:
В будущем это может измениться. См. также: Базовые параметры для всех клиентских методов.
Метод command
Он может использоваться для операторов, которые не возвращают результат, когда предложение FORMAT неприменимо, или когда вам вообще не нужен ответ. Примером такого оператора может быть CREATE TABLE или ALTER TABLE.
Вызов должен ожидаться с помощью await.
Поток ответа немедленно закрывается, что означает, что подлежащий сокет освобождается.
См. также: Базовые параметры для всех клиентских методов.
Пример: (Node.js/Web) Создание таблицы в ClickHouse Cloud. Исходный код.
Пример: (Node.js/Web) создание таблицы в self-hosted экземпляре ClickHouse. Исходный код.
Пример: (Node.js/Web) INSERT FROM SELECT
Отмена запроса с помощью abort_signal не гарантирует, что соответствующий оператор не был выполнен сервером.
Метод exec
Если у вас есть произвольный запрос, который не вписывается в query/insert,
и вам нужен результат, вы можете использовать exec в качестве альтернативы command.
exec возвращает читаемый поток, который ДОЛЖЕН быть обязательно прочитан или уничтожен на стороне приложения.
См. также: Базовые параметры для всех клиентских методов.
Тип возвращаемого значения Stream различается в версиях для Node.js и Web.
Node.js:
Веб:
Ping
Метод ping, предназначенный для проверки состояния подключения, возвращает true, если сервер доступен.
Если сервер недоступен, соответствующая ошибка также включается в результат.
Ping может быть полезным инструментом для проверки доступности сервера при запуске приложения, особенно при работе с ClickHouse Cloud, где экземпляр может простаивать и «просыпается» после ping-запроса: в этом случае имеет смысл повторить его несколько раз с паузой между попытками.
Обратите внимание, что по умолчанию версия для Node.js использует endpoint /ping, тогда как Web-версия выполняет простой запрос SELECT 1 для достижения аналогичного результата, поскольку endpoint /ping не поддерживает CORS.
Пример: (Node.js/Web) простой ping экземпляра сервера ClickHouse. NB: для Web-версии перехватываемые ошибки будут отличаться. Исходный код.
Пример: Если вы хотите при вызове метода ping дополнительно проверять учетные данные или указывать дополнительные параметры, такие как query_id, вы можете использовать его следующим образом:
Метод ping может принимать большинство стандартных параметров метода query — см. определение типа PingParamsWithSelectQuery.
Close (только Node.js)
Закрывает все открытые соединения и освобождает ресурсы. Ничего не делает в веб-версии.
Потоковая передача файлов (только Node.js)
В клиентском репозитории есть несколько примеров потоковой передачи файлов с популярными форматами данных (NDJSON, CSV, Parquet).
- Потоковая передача из файла NDJSON
- Потоковая передача из файла CSV
- Потоковая передача из файла Parquet
- Потоковая передача в файл Parquet
Потоковая передача других форматов в файл должна быть аналогична работе с Parquet; единственное отличие будет в формате, используемом при вызове query (JSONEachRow, CSV и т. д.) и имени выходного файла.
Поддерживаемые форматы данных
Клиент поддерживает форматы данных на основе JSON или текстовые форматы.
Если вы укажете format как один из форматов семейства JSON (JSONEachRow, JSONCompactEachRow и т.д.), клиент будет сериализовывать и десериализовывать данные при передаче по сети.
Данные, предоставленные в «сырых» текстовых форматах (семейства CSV, TabSeparated и CustomSeparated), отправляются по сети без дополнительных преобразований.
Может возникнуть путаница между JSON как общим форматом и форматом ClickHouse JSON.
Клиент поддерживает потоковую передачу JSON-объектов с форматами, такими как JSONEachRow (см. сводную таблицу для других форматов, удобных для потоковой обработки; см. также примеры select_streaming_ в репозитории клиента).
Однако такие форматы, как ClickHouse JSON и некоторые другие, представлены как единый объект в ответе и не могут передаваться потоком со стороны клиента.
| Format | Input (array) | Input (object) | Input/Output (Stream) | Output (JSON) | Output (text) |
|---|---|---|---|---|---|
| JSON | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONCompact | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONObjectEachRow | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONColumnsWithMetadata | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONStrings | ❌ | ❌️ | ❌ | ✔️ | ✔️ |
| JSONCompactStrings | ❌ | ❌ | ❌ | ✔️ | ✔️ |
| JSONEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONEachRowWithProgress | ❌️ | ❌ | ✔️ ❗- см. ниже | ✔️ | ✔️ |
| JSONStringsEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactStringsEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactEachRowWithNames | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactEachRowWithNamesAndTypes | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactStringsEachRowWithNames | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactStringsEachRowWithNamesAndTypes | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| CSV | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CSVWithNames | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CSVWithNamesAndTypes | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparated | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparatedRaw | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparatedWithNames | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparatedWithNamesAndTypes | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CustomSeparated | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CustomSeparatedWithNames | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CustomSeparatedWithNamesAndTypes | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| Parquet | ❌ | ❌ | ✔️ | ❌ | ✔️❗- см. ниже |
Для Parquet основным сценарием использования запросов SELECT, скорее всего, будет запись результирующего потока в файл. См. пример в репозитории клиента.
JSONEachRowWithProgress — это формат только для вывода данных, который поддерживает отчёт о прогрессе в потоке. См. этот пример для получения дополнительной информации.
Полный список входных и выходных форматов ClickHouse доступен здесь.
Поддерживаемые типы данных ClickHouse
Соответствующий тип JS актуален для любых форматов JSON*, кроме тех, которые представляют всё как строку (например, JSONStringEachRow).
| Type | Status | JS type |
|---|---|---|
| UInt8/16/32 | ✔️ | number |
| UInt64/128/256 | ✔️ ❗- см. ниже | string |
| Int8/16/32 | ✔️ | number |
| Int64/128/256 | ✔️ ❗- см. ниже | string |
| Float32/64 | ✔️ | number |
| Decimal | ✔️ ❗- см. ниже | number |
| Boolean | ✔️ | boolean |
| String | ✔️ | string |
| FixedString | ✔️ | string |
| UUID | ✔️ | string |
| Date32/64 | ✔️ | string |
| DateTime32/64 | ✔️ ❗- см. ниже | string |
| Enum | ✔️ | string |
| LowCardinality | ✔️ | string |
| Array(T) | ✔️ | T[] |
| (new) JSON | ✔️ | object |
| Variant(T1, T2...) | ✔️ | T (зависит от варианта) |
| Dynamic | ✔️ | T (зависит от варианта) |
| Nested | ✔️ | T[] |
| Tuple(T1, T2, ...) | ✔️ | [T1, T2, ...] |
| Tuple(n1 T1, n2 T2...) | ✔️ | { n1: T1; n2: T2; ...} |
| Nullable(T) | ✔️ | тип JS для T или null |
| IPv4 | ✔️ | string |
| IPv6 | ✔️ | string |
| Point | ✔️ | [ number, number ] |
| Ring | ✔️ | Array<Point> |
| Polygon | ✔️ | Array<Ring> |
| MultiPolygon | ✔️ | Array<Polygon> |
| Map(K, V) | ✔️ | Record<K, V> |
| Time/Time64 | ✔️ | string |
Полный список поддерживаемых типов данных ClickHouse доступен здесь.
См. также:
Особенности типов Date/Date32
Поскольку клиент вставляет значения без дополнительного преобразования типов, столбцы типа Date/Date32 можно вставлять только в виде строк.
Пример: Вставка значения типа Date.
Исходный код
Однако, если вы используете столбцы с типом DateTime или DateTime64, вы можете использовать как строки, так и объекты JS Date. Объекты JS Date можно передавать в insert как есть, при значении параметра date_time_input_format, установленном в best_effort. Подробнее см. в этом примере.
Особенности типов Decimal*
Можно вставлять значения Decimal с помощью форматов семейства JSON*. Предположим, у нас есть таблица, определённая как:
Значения можно вставлять без потери точности, используя строковое представление:
Однако при запросе данных в форматах JSON* ClickHouse по умолчанию будет возвращать значения типов Decimal как числа, что может привести к потере точности. Чтобы этого избежать, вы можете приводить значения Decimal к строке в запросе:
См. этот пример для получения дополнительных сведений.
Целочисленные типы: Int64, Int128, Int256, UInt64, UInt128, UInt256
Хотя сервер может принимать это значение как число, в выходных форматах семейства JSON* оно возвращается как строка, чтобы избежать
переполнения целого числа, поскольку максимальные значения этих типов превышают Number.MAX_SAFE_INTEGER.
Однако это поведение можно изменить с помощью настройки output_format_json_quote_64bit_integers.
Пример: Настройка формата вывода JSON для 64-битных чисел.
Настройки ClickHouse
Клиент может настраивать поведение ClickHouse с помощью механизма настроек. Настройки можно задать на уровне экземпляра клиента, чтобы они применялись к каждому запросу, отправляемому в ClickHouse:
Или параметр можно настроить на уровне отдельного запроса:
Файл объявлений типов со всеми поддерживаемыми настройками ClickHouse можно найти здесь.
Убедитесь, что пользователь, от имени которого выполняются запросы, имеет достаточные права для изменения настроек.
Продвинутые темы
Запросы с параметрами
Вы можете создать запрос с параметрами и передавать значения для них из клиентского приложения. Это позволяет избежать формирования запроса с конкретными динамическими значениями на стороне клиента.
Сформируйте запрос как обычно, затем заключите в фигурные скобки значения, которые вы хотите передать из параметров приложения в запрос, в следующем формате:
где:
name— идентификатор плейсхолдера.data_type- Тип данных значения параметра приложения.
Пример: Запрос с параметрами.
Исходный код.
Дополнительные сведения см. на странице https://clickhouse.com/docs/interfaces/cli#cli-queries-with-parameters-syntax.
Сжатие
Примечание: сжатие запросов в настоящее время недоступно в веб-версии. Сжатие ответов работает как обычно. Версия для Node.js поддерживает оба варианта.
Приложения для работы с данными, передающие по сети большие объёмы, могут существенно выиграть от включения сжатия. На данный момент поддерживается только GZIP с использованием zlib.
Параметры конфигурации следующие:
response: trueуказывает серверу ClickHouse отправлять сжатое тело ответа. Значение по умолчанию:response: falserequest: trueвключает сжатие тела запроса, отправляемого клиентом. Значение по умолчанию:request: false
Логирование (только Node.js)
Функциональность логирования является экспериментальной и может измениться в будущем.
Реализация логгера по умолчанию выводит записи логов в stdout через методы console.debug/info/warn/error.
Вы можете настроить логику логирования, указав LoggerClass, и выбрать нужный уровень логирования с помощью параметра level (по умолчанию OFF):
В настоящее время клиент записывает в лог следующие события:
TRACE— низкоуровневая информация о жизненном цикле сокетов Keep-AliveDEBUG— информация об ответе (без заголовков авторизации и сведений о хосте)INFO— в основном не используется, выводит текущий уровень логирования при инициализации клиентаWARN— нефатальные ошибки; неуспешный запросpingзаписывается как предупреждение, так как исходная ошибка включена в возвращаемый результатERROR— фатальные ошибки, возникающие в методахquery/insert/exec/command, например, при неуспешном запросе
Реализацию Logger по умолчанию можно найти здесь.
Сертификаты TLS (только для Node.js)
Клиент Node.js опционально поддерживает как односторонний (только центр сертификации, Certificate Authority), так и взаимный (центр сертификации и клиентские сертификаты, Certificate Authority and client certificates) TLS.
Пример базовой конфигурации TLS, если ваши сертификаты находятся в папке certs,
а имя файла CA — CA.pem:
Пример конфигурации взаимного TLS на основе клиентских сертификатов:
Полные примеры конфигурации TLS для режимов basic и mutual см. в репозитории.
Конфигурация Keep-Alive (только для Node.js)
Клиент по умолчанию включает Keep-Alive во внутреннем HTTP-агенте. Это означает, что установленные сокеты будут повторно использоваться для последующих запросов, а заголовок Connection: keep-alive будет отправляться автоматически. Сокеты, простаивающие без активности, по умолчанию остаются в пуле соединений 2500 миллисекунд (см. заметки по настройке этого параметра).
Значение keep_alive.idle_socket_ttl рекомендуется задавать заметно ниже, чем соответствующую настройку на стороне сервера/балансировщика нагрузки (LB). Основная причина в том, что HTTP/1.1 допускает закрытие сокетов сервером без уведомления клиента. Если сервер или балансировщик нагрузки закроет соединение раньше, чем это сделает клиент, клиент может попытаться повторно использовать уже закрытый сокет, что приведёт к ошибке socket hang up.
Если вы изменяете keep_alive.idle_socket_ttl, имейте в виду, что его значение всегда должно быть согласовано с конфигурацией Keep-Alive на сервере/LB и всегда ниже неё, чтобы гарантировать, что сервер никогда не закроет открытое соединение первым.
Настройка idle_socket_ttl
Клиент устанавливает keep_alive.idle_socket_ttl в 2500 миллисекунд, так как это можно считать наиболее безопасным значением по умолчанию; на стороне сервера keep_alive_timeout может быть установлен на значение всего 3 секунды в версиях ClickHouse до 23.11 без изменений в config.xml.
Если вас устраивает производительность и вы не сталкиваетесь с какими‑либо проблемами, рекомендуется не увеличивать значение настройки keep_alive.idle_socket_ttl, так как это может привести к возможным ошибкам «Socket hang-up»; кроме того, если ваше приложение отправляет много запросов и между ними нет больших простоев, значения по умолчанию должно быть достаточно, так как сокеты не будут простаивать достаточно долго, и клиент будет удерживать их в пуле.
Вы можете найти корректное значение таймаута Keep-Alive в заголовках ответа сервера, выполнив следующую команду:
Проверьте значения заголовков Connection и Keep-Alive в ответе. Например:
В данном случае keep_alive_timeout равен 10 секундам, и вы можете попробовать увеличить keep_alive.idle_socket_ttl до 9000 или даже 9500 миллисекунд, чтобы неактивные сокеты оставались открытыми немного дольше, чем по умолчанию. Следите за возможными ошибками «Socket hang-up», которые будут указывать на то, что сервер закрывает соединения раньше клиента, и снижайте значение до тех пор, пока ошибки не исчезнут.
Поиск и устранение неисправностей
Если вы сталкиваетесь с ошибками socket hang up, даже используя последнюю версию клиента, есть следующие варианты решения этой проблемы:
-
Включите журналирование как минимум с уровнем
WARN. Это позволит проверить, есть ли в коде приложения непрочитанный или «висящий» поток: транспортный уровень залогирует это на уровне WARN, так как это потенциально может привести к закрытию сокета сервером. Журналирование можно включить в конфигурации клиента следующим образом: -
Проверьте код вашего приложения с включённым правилом ESLint no-floating-promises, которое поможет выявить необработанные промисы, способные приводить к висячим потокам и сокетам.
-
Незначительно уменьшите значение настройки
keep_alive.idle_socket_ttlв конфигурации сервера ClickHouse. В определённых ситуациях, например, при высокой сетевой задержке между клиентом и сервером, может быть полезно уменьшитьkeep_alive.idle_socket_ttlещё на 200–500 миллисекунд, исключив ситуацию, когда исходящий запрос получает сокет, который сервер собирается закрыть. -
Если эта ошибка возникает во время длительных запросов без входящих или исходящих данных (например, долгий
INSERT FROM SELECT), это может быть связано с тем, что балансировщик нагрузки закрывает простаивающие соединения. Можно попытаться принудительно инициировать передачу некоторых данных во время длительных запросов, используя комбинацию следующих настроек ClickHouse:Однако имейте в виду, что общий размер полученных заголовков имеет ограничение 16KB в последних версиях Node.js; после получения определённого количества заголовков прогресса, которое в наших тестах составляло примерно 70–80, будет сгенерировано исключение.
Также возможно использовать полностью другой подход, полностью избегая ожидания по сети; это можно сделать, используя «особенность» HTTP-интерфейса, заключающуюся в том, что мутации не отменяются при потере соединения. См. этот пример (часть 2) для подробностей.
-
Механизм Keep-Alive можно полностью отключить. В этом случае клиент также будет добавлять заголовок
Connection: closeк каждому запросу, и базовый HTTP-агент не будет переиспользовать соединения. Настройкаkeep_alive.idle_socket_ttlбудет проигнорирована, так как простаивающих сокетов не будет. Это приведёт к дополнительным накладным расходам, поскольку для каждого запроса будет устанавливаться новое соединение.
Пользователи только для чтения
При использовании клиента с пользователем с readonly=1 сжатие ответа не может быть включено, так как для этого требуется параметр enable_http_compression. Следующая конфигурация приведёт к ошибке:
См. пример, где подробнее показаны ограничения пользователя с readonly=1.
Прокси с путем (pathname)
Если ваш экземпляр ClickHouse находится за прокси и в его URL-адресе есть путь (pathname), как, например, http://proxy:8123/clickhouse_server, укажите clickhouse_server в качестве параметра конфигурации pathname (с начальным слешем или без него); иначе, если этот путь указан напрямую в url, он будет интерпретирован как параметр database. Поддерживается несколько сегментов, например /my_proxy/db.
Реверс‑прокси с аутентификацией
Если перед вашим развертыванием ClickHouse стоит реверс‑прокси с аутентификацией, вы можете использовать параметр http_headers, чтобы передавать необходимые заголовки:
Пользовательский HTTP/HTTPS-агент (экспериментальная функция, только Node.js)
Это экспериментальная функция, которая в будущих релизах может измениться с нарушением обратной совместимости. Реализация и настройки по умолчанию, предоставляемые клиентом, должны быть достаточны для большинства сценариев использования. Используйте эту функцию только в том случае, если вы уверены, что она вам действительно необходима.
По умолчанию клиент настраивает внутренний HTTP(s)-агент, используя параметры, заданные в конфигурации клиента (такие как max_open_connections, keep_alive.enabled, tls), и именно он обрабатывает подключения к серверу ClickHouse. Дополнительно, если используются TLS-сертификаты, внутренний агент будет настроен с необходимыми сертификатами, и будут применены корректные заголовки аутентификации TLS.
Начиная с версии 1.2.0, можно передать клиенту пользовательский HTTP(s)-агент, заменив стандартный внутренний агент. Это может быть полезно в случае сложной сетевой конфигурации. Если передан пользовательский агент, применяются следующие условия:
- Параметры
max_open_connectionsиtlsне будут иметь никакого эффекта и будут проигнорированы клиентом, так как они являются частью конфигурации внутреннего агента. keep_alive.enabledбудет регулировать только значение по умолчанию заголовкаConnection(true->Connection: keep-alive,false->Connection: close).- Хотя управление неактивными keep-alive-сокетами по-прежнему будет работать (так как оно не привязано к агенту, а к конкретному сокету), теперь можно полностью отключить его, установив значение
keep_alive.idle_socket_ttlв0.
Примеры использования кастомного агента
Использование кастомного HTTP(S)-агента без сертификатов:
Использование пользовательского HTTPS-агента с базовым TLS и сертификатом удостоверяющего центра (CA):
Использование настраиваемого HTTPS-агента с взаимной TLS-аутентификацией:
При использовании сертификатов и пользовательского HTTPS-агента, скорее всего, потребуется отключить заголовок авторизации по умолчанию с помощью настройки set_basic_auth_header (добавлена в 1.2.0), так как он конфликтует с заголовками TLS. Все заголовки TLS должны задаваться вручную.
Известные ограничения (Node.js/web)
- Для результирующих наборов не предусмотрены мапперы данных, поэтому используются только примитивы языка. Планируется добавление некоторых мапперов типов данных с поддержкой формата RowBinary.
- Существуют некоторые особенности типов данных Decimal* и Date* / DateTime*.
- При использовании форматов семейства JSON* числа, превышающие Int32, представляются в виде строк, так как максимальные значения типов Int64+ больше, чем
Number.MAX_SAFE_INTEGER. Подробнее см. в разделе Integral types.
Известные ограничения (web)
- Потоковая обработка для запросов SELECT поддерживается, но отключена для операций INSERT (в том числе на уровне типов).
- Сжатие запросов отключено, настройка игнорируется. Сжатие ответов работает.
- Поддержка логирования пока отсутствует.
Советы по оптимизации производительности
- Чтобы уменьшить потребление памяти приложением, рассмотрите возможность использования потоков для больших вставок (например, из файлов) и выборок, когда это применимо. Для слушателей событий и схожих сценариев использования асинхронные вставки могут быть ещё одним хорошим вариантом, позволяя минимизировать или даже полностью избежать батчирования на стороне клиента. Примеры асинхронных вставок доступны в репозитории клиента — с префиксом
async_insert_в имени файла. - Клиент по умолчанию не использует сжатие запросов или ответов. Однако при выборке или вставке больших наборов данных вы можете рассмотреть возможность включения сжатия через
ClickHouseClientConfigOptions.compression(либо только дляrequestилиresponse, либо для обоих). - Сжатие даёт существенные накладные расходы. Включение его для
requestилиresponseнегативно скажется на скорости выборок или вставок соответственно, но уменьшит объём сетевого трафика, передаваемого приложением.
Связаться с нами
Если у вас есть вопросы или нужна помощь, вы можете написать нам в Community Slack (канал #clickhouse-js) или через раздел issues на GitHub.