Клиентская библиотека Java для взаимодействия с сервером базы данных через его протоколы. Текущая реализация поддерживает только HTTP-интерфейс. Библиотека предоставляет собственный API для отправки запросов на сервер. Также библиотека содержит инструменты для работы с различными бинарными форматами данных (RowBinary* & Native*).
Setup
- Maven Central (веб-страница проекта): https://mvnrepository.com/artifact/com.clickhouse/client-v2
- Ночные сборки (ссылка на репозиторий): https://central.sonatype.com/repository/maven-snapshots/
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>client-v2</artifactId>
<version>0.9.8</version>
</dependency>// https://mvnrepository.com/artifact/com.clickhouse/client-v2
implementation("com.clickhouse:client-v2:0.9.8")// https://mvnrepository.com/artifact/com.clickhouse/client-v2
implementation 'com.clickhouse:client-v2:0.9.8'Инициализация
Объект Client инициализируется с помощью com.clickhouse.client.api.Client.Builder#build(). Каждый клиент имеет собственный контекст, и между клиентами не разделяются объекты.
Builder предоставляет методы конфигурации для удобной настройки.
Пример:
Client client = new Client.Builder()
.addEndpoint("https://clickhouse-cloud-instance:8443/")
.setUsername(user)
.setPassword(password)
.build();Client реализует AutoCloseable и должен быть закрыт, когда больше не нужен.
Аутентификация
Аутентификация настраивается для каждого клиента на этапе инициализации. Поддерживаются три метода аутентификации: по паролю, по токену доступа, по SSL-сертификату клиента.
Аутентификация по паролю требует указания имени пользователя и пароля через вызовы setUsername(String) и setPassword(String):
Client client = new Client.Builder()
.addEndpoint("https://clickhouse-cloud-instance:8443/")
.setUsername(user)
.setPassword(password)
.build();Для аутентификации с помощью токена доступа необходимо задать токен доступа, вызвав setAccessToken(String):
Client client = new Client.Builder()
.addEndpoint("https://clickhouse-cloud-instance:8443/")
.setAccessToken(userAccessToken)
.build();Аутентификация с помощью SSL-сертификата клиента требует указания имени пользователя, включения SSL-аутентификации, а также задания клиентского сертификата и клиентского ключа посредством вызовов setUsername(String), useSSLAuthentication(boolean), setClientCertificate(String) и setClientKey(String) соответственно:
Client client = new Client.Builder()
.useSSLAuthentication(true)
.setUsername("some_user")
.setClientCertificate("some_user.crt")
.setClientKey("some_user.key")Конфигурация
Все настройки определяются методами экземпляра (они же методы конфигурации), которые чётко задают область видимости и контекст каждого значения. Основные параметры конфигурации определяются в одной области видимости (клиента или операции) и не переопределяют друг друга.
Конфигурация задаётся при создании клиента. См. com.clickhouse.client.api.Client.Builder.
Конфигурация клиента
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
addEndpoint(String endpoint) |
endpoint - адрес сервера в формате URL |
Добавляет конечную точку сервера в список доступных серверов. Сейчас поддерживается только одна конечная точка. | none |
none |
addEndpoint(Protocol protocol, String host, int port, boolean secure) |
protocol - протокол соединенияhost - IP-адрес или имя хостаsecure - использовать HTTPS |
Добавляет конечную точку сервера в список доступных серверов. Сейчас поддерживается только одна конечная точка. | none |
none |
enableConnectionPool(boolean enable) |
enable - флаг включения/отключения |
Определяет, включен ли пул соединений | true |
connection_pool_enabled |
setMaxConnections(int maxConnections) |
maxConnections - количество соединений |
Задает, сколько соединений клиент может открыть для каждой конечной точки сервера. | 10 |
max_open_connections |
setConnectionTTL(long timeout, ChronoUnit unit) |
timeout - значение тайм-аутаunit - единица времени |
Задает TTL соединения, по истечении которого оно считается неактивным | -1 |
connection_ttl |
setKeepAliveTimeout(long timeout, ChronoUnit unit) |
timeout - значение тайм-аутаunit - единица времени |
Задает тайм-аут Keep-Alive для HTTP-соединения. Установите 0, чтобы отключить Keep-Alive. |
- | http_keep_alive_timeout |
setConnectionReuseStrategy(ConnectionReuseStrategy strategy) |
strategy - LIFO или FIFO |
Выбирает стратегию, которую должен использовать пул соединений | FIFO |
connection_reuse_strategy |
setDefaultDatabase(String database) |
database - имя базы данных |
Задает базу данных по умолчанию. | default |
database |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
setUsername(String username) |
username - имя пользователя для аутентификации |
Устанавливает имя пользователя для метода аутентификации, который выбирается дальнейшей конфигурацией | default |
user |
setPassword(String password) |
password - секретное значение |
Устанавливает секрет для аутентификации по паролю и фактически выбирает этот метод аутентификации | - | password |
setAccessToken(String accessToken) |
accessToken - строка токена доступа |
Устанавливает токен доступа для аутентификации и выбирает соответствующий метод аутентификации | - | access_token |
useSSLAuthentication(boolean useSSLAuthentication) |
useSSLAuthentication - флаг для включения SSL-аутентификации |
Устанавливает SSL-сертификат клиента в качестве метода аутентификации. | - | ssl_authentication |
useHTTPBasicAuth(boolean useBasicAuth) |
useBasicAuth - флаг для включения/отключения |
Указывает, следует ли использовать HTTP-аутентификацию Basic для аутентификации по имени пользователя и паролю. Решает проблемы с паролями, содержащими специальные символы. | true |
http_use_basic_auth |
useBearerTokenAuth(String bearerToken) |
bearerToken - закодированный Bearer-токен |
Указывает, следует ли использовать Bearer-аутентификацию и какой токен использовать. Токен будет отправлен как есть. | - | bearer_token |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
setConnectTimeout(long timeout, ChronoUnit unit) |
timeout - значение тайм-аутаunit - единица времени |
Устанавливает тайм-аут установления любого исходящего соединения. | - | connection_timeout |
setConnectionRequestTimeout(long timeout, ChronoUnit unit) |
timeout - значение тайм-аутаunit - единица времени |
Устанавливает тайм-аут запроса соединения. Применяется только при получении соединения из пула. | 10000 |
connection_request_timeout |
setSocketTimeout(long timeout, ChronoUnit unit) |
timeout - значение тайм-аутаunit - единица времени |
Устанавливает тайм-аут сокета, влияющий на операции чтения и записи | 0 |
socket_timeout |
setExecutionTimeout(long timeout, ChronoUnit timeUnit) |
timeout - значение тайм-аутаtimeUnit - единица времени |
Устанавливает максимальный тайм-аут выполнения запросов | 0 |
max_execution_time |
retryOnFailures(ClientFaultCause ...causes) |
causes - константы перечисления ClientFaultCause |
Задаёт типы сбоев, для которых возможно восстановление или повторная попытка. | NoHttpResponse ConnectTimeout ConnectionRequestTimeout |
client_retry_on_failures |
setMaxRetries(int maxRetries) |
maxRetries - количество повторных попыток |
Устанавливает максимальное число повторных попыток для сбоев, заданных в retryOnFailures |
3 |
retry |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
setSocketRcvbuf(long size) |
size - размер в байтах |
Задает размер буфера приема TCP-сокета. Этот буфер находится вне памяти JVM. | 8196 |
socket_rcvbuf |
setSocketSndbuf(long size) |
size - размер в байтах |
Задает размер буфера отправки TCP-сокета. Этот буфер находится вне памяти JVM. | 8196 |
socket_sndbuf |
setSocketKeepAlive(boolean value) |
value - флаг включения/отключения |
Задает параметр SO_KEEPALIVE для каждого TCP-сокета. Механизм TCP Keep Alive позволяет проверять, активно ли соединение. |
- | socket_keepalive |
setSocketTcpNodelay(boolean value) |
value - флаг включения/отключения |
Задает параметр SO_NODELAY для каждого TCP-сокета. Этот параметр TCP заставляет сокет отправлять данные как можно быстрее. |
- | socket_tcp_nodelay |
setSocketLinger(int secondsToWait) |
secondsToWait - количество секунд |
Задает время ожидания при закрытии для каждого TCP-сокета, созданного клиентом. | - | socket_linger |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
compressServerResponse(boolean enabled) |
enabled - флаг для включения/отключения |
Задает, должен ли сервер сжимать свои ответы. | true |
compress |
compressClientRequest(boolean enabled) |
enabled - флаг для включения/отключения |
Задает, должен ли клиент сжимать свои запросы. | false |
decompress |
useHttpCompression(boolean enabled) |
enabled - флаг для включения/отключения |
Задает, следует ли использовать HTTP-сжатие при обмене данными между клиентом и сервером, если включены соответствующие параметры | - | - |
appCompressedData(boolean enabled) |
enabled - флаг для включения/отключения |
Сообщает клиенту, что сжатием будет управлять приложение. | false |
app_compressed_data |
setLZ4UncompressedBufferSize(int size) |
size - размер в байтах |
Задает размер буфера, в который будет поступать несжатая часть потока данных. | 65536 |
compression.lz4.uncompressed_buffer_size |
disableNativeCompression |
disable - флаг для отключения |
Отключает нативное сжатие. Если задано значение true, нативное сжатие будет отключено. | false |
disable_native_compression |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
setSSLTrustStore(String path) |
path - путь к файлу в локальной системе |
Задает путь к SSL truststore, которое клиент будет использовать для проверки хоста сервера. | - | trust_store |
setSSLTrustStorePassword(String password) |
password - секретное значение |
Задает пароль для разблокировки SSL truststore, указанного в setSSLTrustStore. |
- | key_store_password |
setSSLTrustStoreType(String type) |
type - имя типа truststore |
Задает тип truststore, указанного в setSSLTrustStore. |
- | key_store_type |
setRootCertificate(String path) |
path - путь к файлу в локальной системе |
Задает путь к корневому сертификату (CA), который клиент будет использовать для проверки хоста сервера. | - | sslrootcert |
setClientCertificate(String path) |
path - путь к файлу в локальной системе |
Задает путь к сертификату клиента, который будет использоваться при установлении SSL‑соединения и для SSL-аутентификации. | - | sslcert |
setClientKey(String path) |
path - путь к файлу в локальной системе |
Задает путь к закрытому ключу клиента, который будет использоваться для шифрования SSL‑соединения с сервером. | - | ssl_key |
sslSocketSNI(String sni) |
sni - строка имени сервера |
Задает имя сервера, которое будет использоваться для SNI (Server Name Indication) в SSL/TLS‑соединении. | - | ssl_socket_sni |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
addProxy(ProxyType type, String host, int port) |
type - тип проксиhost - имя хоста или IP-адрес проксиport - порт прокси |
Задаёт прокси для связи с сервером. | - | proxy_type, proxy_host, proxy_port |
setProxyCredentials(String user, String pass) |
user - имя пользователя проксиpass - пароль |
Задаёт учетные данные для аутентификации через прокси. | - | proxy_user, proxy_password |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
setHttpCookiesEnabled(boolean enabled) |
enabled - флаг включения/отключения |
Указывает, следует ли запоминать HTTP cookie и отправлять их обратно серверу. | - | - |
httpHeader(String key, String value) |
key - ключ HTTP-заголовкаvalue - строковое значение |
Задает значение одного HTTP-заголовка. Предыдущее значение переопределяется. | none |
none |
httpHeader(String key, Collection values) |
key - ключ HTTP-заголовкаvalues - список строковых значений |
Задает значения одного HTTP-заголовка. Предыдущее значение переопределяется. | none |
none |
httpHeaders(Map headers) |
headers - map с HTTP-заголовками |
Задает сразу несколько HTTP-заголовков. | none |
none |
useHttpFormDataForQuery(boolean enable) |
enable - флаг включения/отключения |
Указывает, следует ли отправлять параметры запроса как данные HTTP-формы в теле запроса, а не в URL. Работает только при сжатии на стороне сервера. Если включено сжатие на уровне клиента, оно будет отключено для запросов с параметрами, так как каждый параметр отправляется как multipart-содержимое. | false |
client.http.use_form_request_for_query |
| Method | Arguments | Description | Default | Key |
|---|---|---|---|---|
serverSetting(String name, String value) |
name - имя настройкиvalue - значение настройки |
Задаёт, какие настройки передавать на сервер с каждым запросом. Настройки отдельных операций могут их переопределять. Список настроек | none |
none |
serverSetting(String name, Collection values) |
name - имя настройкиvalues - значения настройки |
Задаёт, какие настройки с несколькими значениями передавать на сервер, например роли | none |
none |
setOption("custom_settings_prefix", value) |
value - строка префикса |
Задаёт префикс для пользовательских настроек, передаваемых на сервер. Он должен соответствовать конфигурации сервера. См. ClickHouse Docs. | custom_ |
custom_settings_prefix |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
useServerTimeZone(boolean useServerTimeZone) |
useServerTimeZone — флаг включения/отключения |
Указывает, должен ли клиент использовать часовой пояс сервера при декодировании значений в столбцах DateTime и Date. | true |
use_server_time_zone |
useTimeZone(String timeZone) |
timeZone — допустимый ID часового пояса Java |
Указывает, следует ли использовать указанный часовой пояс при декодировании значений в столбцах DateTime и Date. Переопределяет часовой пояс сервера. | - | use_time_zone |
setServerTimeZone(String timeZone) |
timeZone — допустимый ID часового пояса Java |
Задает часовой пояс на стороне сервера. По умолчанию используется часовой пояс UTC. | UTC |
server_time_zone |
| Метод | Аргументы | Описание | По умолчанию | Ключ |
|---|---|---|---|---|
setOption(String key, String value) |
key - ключ параметра конфигурацииvalue - значение параметра |
Устанавливает исходное значение параметров клиента. Полезно при чтении конфигурации из файлов свойств. | - | - |
useAsyncRequests(boolean async) |
async - флаг включения/отключения |
Определяет, должен ли клиент выполнять запрос в отдельном потоке. По умолчанию отключено, поскольку приложение лучше знает, как организовать многопоточные задачи. | false |
async |
setSharedOperationExecutor(ExecutorService executorService) |
executorService - экземпляр сервиса-исполнителя |
Задает сервис-исполнитель для задач операций. | none |
none |
setQueryIdGenerator(Supplier<String> supplier) |
supplier - Supplier<String>, генерирующий Query id |
Устанавливает пользовательский генератор Query id, который используется, если идентификатор запроса не указан в настройках операции (InsertSettings, QuerySettings). |
- | - |
setClientNetworkBufferSize(int size) |
size - размер в байтах |
Задает размер буфера в памяти приложения, который используется для копирования данных между сокетом и приложением. | 300000 |
client_network_buffer_size |
allowBinaryReaderToReuseBuffers(boolean reuse) |
reuse - флаг включения/отключения |
Если параметр включен, reader будет использовать предварительно выделенные буферы для преобразования чисел. Это снижает нагрузку на GC при работе с числовыми данными. | - | - |
columnToMethodMatchingStrategy(ColumnToMethodMatchingStrategy strategy) |
strategy - реализация стратегии сопоставления |
Устанавливает пользовательскую стратегию сопоставления полей класса DTO и столбцов DB при регистрации DTO. | none |
none |
setClientName(String clientName) |
clientName - строка с именем приложения |
Задает дополнительную информацию о вызывающем приложении. Она будет передаваться в заголовке User-Agent. |
- | client_name |
registerClientMetrics(Object registry, String name) |
registry - экземпляр registry Micrometername - имя группы метрик |
Регистрирует сенсоры в registry Micrometer (https://micrometer.io/). | - | - |
setServerVersion(String version) |
version - строка версии сервера |
Задает версию сервера, чтобы избежать ее автоматического определения. | - | server_version |
typeHintMapping(Map typeHintMapping) |
typeHintMapping - map подсказок типа |
Задает сопоставление подсказок типа для типов ClickHouse. Например, чтобы многомерные массивы были представлены как контейнеры Java. | - | type_hint_mapping |
Идентификация клиента
В журнале запросов есть два поля, по которым можно определить приложение, из которого был отправлен запрос: client_name и http_user_agent. Нативный TCP-протокол использует
client_name для идентификации приложения. HTTP-протокол использует http_user_agent для идентификации приложения. В билдере клиента есть метод setClientName, который задаёт корректные значения
для обоих протоколов.
Поле http_user_agent задаётся в соответствии с общепринятым форматом заголовка User-Agent: application-name[/version] [(operating-system; architecture; ...)].
Этот набор значений повторяется для каждого уровня: приложение, клиентская библиотека, HTTP-клиентская библиотека. Значение, заданное методом setClientName, идёт первым в списке.
Например:
client.setClientName("my-app-01/1.0");приведёт к следующему значению http_user_agent:
my-app-01/1.0 clickhouse-java-v2/0.9.6-SNAPSHOT (Linux; jvm:17.0.17) Apache-HttpClient/5.4.4Приложение может задать собственный HTTP-заголовок User-Agent для идентификации. При этом строка clickhouse-java-v2/0.9.6-SNAPSHOT будет добавлена в конец заголовка.
Идентификация операции
Log запросов содержит ещё два поля — query_id и log_comment, — которые можно использовать для идентификации операции и добавления дополнительных сведений в log запросов.
query_id — уникальный идентификатор операции. Его можно задать в приложении, вызвав метод setQueryId класса QuerySettings.
QuerySettings querySettings = new QuerySettings();
querySettings.setQueryId("some-query-id");log_comment — это комментарий, который можно добавить в лог запросов. Его можно задать в приложении, вызвав метод logComment класса QuerySettings.
QuerySettings querySettings = new QuerySettings();
querySettings.logComment("some-comment");Настройки сервера
Настройки на стороне сервера можно задать на уровне клиента один раз при создании (см. метод serverSetting класса Builder) и на уровне операции (см. serverSetting для класса настроек операции).
try (Client client = new Client.Builder().addEndpoint(Protocol.HTTP, "localhost", mockServer.port(), false)
.setUsername("default")
.setPassword(ClickHouseServerForTest.getPassword())
.compressClientRequest(true)
// Client level
.serverSetting("max_threads", "10")
.serverSetting("async_insert", "1")
.serverSetting("roles", Arrays.asList("role1", "role2"))
.build()) {
// Operation level
QuerySettings querySettings = new QuerySettings();
querySettings.serverSetting("session_timezone", "Europe/Zurich");
...
}⚠️ Если параметры задаются через метод setOption (будь то Client.Builder или класс настроек операции), имя настройки сервера должно иметь префикс clickhouse_setting_. В этом случае может пригодиться com.clickhouse.client.api.ClientConfigProperties#serverSetting().
Пользовательский HTTP-заголовок
Пользовательские HTTP-заголовки можно задать для всех операций (на уровне клиента) или для отдельной операции (на уровне операции).
QuerySettings settings = new QuerySettings()
.httpHeader(HttpHeaders.REFERER, clientReferer)
.setQueryId(qId);Если параметры задаются через метод setOption (будь то Client.Builder или класс настроек операции), имя пользовательского заголовка должно начинаться с префикса http_header_. В этом случае может пригодиться метод com.clickhouse.client.api.ClientConfigProperties#httpHeader().
Общие определения
ClickHouseFormat
Перечисление поддерживаемых форматов. Включает все форматы, поддерживаемые ClickHouse.
raw- пользователь должен перекодировать необработанные данныеfull- клиент может самостоятельно перекодировать данные и принимает поток необработанных данных-- операция не поддерживается ClickHouse для этого формата
Эта версия клиента поддерживает:
API вставки
insert(String tableName, InputStream data, ClickHouseFormat format)
Принимает данные в виде InputStream байтов в указанном формате. Предполагается, что data закодированы в формате format.
Сигнатуры
CompletableFuture<InsertResponse> insert(String tableName, InputStream data, ClickHouseFormat format, InsertSettings settings)
CompletableFuture<InsertResponse> insert(String tableName, InputStream data, ClickHouseFormat format)Параметры
tableName — имя целевой таблицы.
data — входной поток закодированных данных.
format — формат, в котором закодированы данные.
settings - параметры запроса.
Возвращаемое значение
Future типа InsertResponse — результат операции и дополнительная информация, например метрики на стороне сервера.
Примеры
try (InputStream dataStream = getDataStream()) {
try (InsertResponse response = client.insert(TABLE_NAME, dataStream, ClickHouseFormat.JSONEachRow,
insertSettings).get(3, TimeUnit.SECONDS)) {
log.info("Insert finished: {} rows written", response.getMetrics().getMetric(ServerMetrics.NUM_ROWS_WRITTEN).getLong());
} catch (Exception e) {
log.error("Failed to write JSONEachRow data", e);
throw new RuntimeException(e);
}
}insert(String tableName, List<?> data, InsertSettings settings)
Отправляет запрос на запись в базу данных. Список объектов преобразуется в эффективный формат и затем отправляется на сервер. Класс элементов списка должен быть заранее зарегистрирован с помощью метода register(Class, TableSchema).
Сигнатуры
client.insert(String tableName, List<?> data, InsertSettings settings)
client.insert(String tableName, List<?> data)Параметры
tableName — имя целевой таблицы.
data — коллекция объектов DTO (Data Transfer Object).
settings - параметры запроса.
Возвращаемое значение
Future типа InsertResponse — результат операции и дополнительная информация, например метрики на стороне сервера.
Примеры
// Important step (done once) - register class to pre-compile object serializer according to the table schema.
client.register(ArticleViewEvent.class, client.getTableSchema(TABLE_NAME));
List<ArticleViewEvent> events = loadBatch();
try (InsertResponse response = client.insert(TABLE_NAME, events).get()) {
// handle response, then it will be closed and connection that served request will be released.
}InsertSettings
Параметры для операций вставки.
Методы конфигурации
| Метод | Описание |
|---|---|
setQueryId(String queryId) |
Устанавливает идентификатор запроса, который будет присвоен операции. По умолчанию: null. |
setDeduplicationToken(String token) |
Устанавливает токен дедупликации. Этот токен будет отправлен на сервер и может использоваться для идентификации запроса. По умолчанию: null. |
setInputStreamCopyBufferSize(int size) |
Размер буфера копирования. Буфер используется при операциях записи для копирования данных из входного потока, заданного пользователем, в выходной поток. По умолчанию: 8196. |
serverSetting(String name, String value) |
Устанавливает отдельные настройки сервера для операции. |
serverSetting(String name, Collection values) |
Устанавливает отдельные настройки сервера с несколькими значениями для операции. Элементы коллекции должны иметь тип String. |
setDBRoles(Collection dbRoles) |
Задает роли БД, которые будут установлены перед выполнением операции. Элементы коллекции должны быть строковыми значениями String. |
setOption(String option, Object value) |
Задаёт параметр конфигурации в исходном формате. Это не настройка сервера. |
InsertResponse
Объект ответа, содержащий результат операции вставки. Доступен только в том случае, если клиент получил ответ от сервера.
| Метод | Описание |
|---|---|
OperationMetrics getMetrics() |
Возвращает объект с метриками операции. |
String getQueryId() |
Возвращает Query id, назначенный операции приложением (через настройки операции) или сервером. |
API запросов
query(String sqlQuery)
Отправляет sqlQuery как есть. Формат ответа задаётся настройками запроса. QueryResponse будет содержать ссылку на поток ответа, который должен быть прочитан (consumed) ридер-ом для поддерживаемого формата.
Сигнатуры
CompletableFuture<QueryResponse> query(String sqlQuery, QuerySettings settings)
CompletableFuture<QueryResponse> query(String sqlQuery)Параметры
sqlQuery — один SQL-оператор. Запрос отправляется на сервер как есть.
settings - параметры запроса.
Возвращаемое значение
Future типа QueryResponse — результирующий набор данных и дополнительная информация, например метрики на стороне сервера. Объект Response следует закрыть после обработки набора данных.
Примеры
final String sql = "select * from " + TABLE_NAME + " where title <> '' limit 10";
// Default format is RowBinaryWithNamesAndTypesFormatReader so reader have all information about columns
try (QueryResponse response = client.query(sql).get(3, TimeUnit.SECONDS);) {
// Create a reader to access the data in a convenient way
ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);
while (reader.hasNext()) {
reader.next(); // Read the next record from stream and parse it
// get values
double id = reader.getDouble("id");
String title = reader.getString("title");
String url = reader.getString("url");
// collecting data
}
} catch (Exception e) {
log.error("Failed to read data", e);
}
// put business logic outside of the reading block to release http connection asap.query(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)
Отправляет sqlQuery без изменений. Также отправляет параметры запроса, чтобы сервер мог скомпилировать SQL-выражение.
Сигнатуры
CompletableFuture<QueryResponse> query(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)Параметры
sqlQuery — SQL-выражение с плейсхолдерами {}.
queryParams — набор переменных для подстановки в SQL-выражение на сервере.
settings - параметры запроса.
Возвращаемое значение
Future типа QueryResponse — результирующий набор данных и дополнительная информация, например метрики на стороне сервера. Объект Response следует закрыть после обработки набора данных.
Примеры
// define parameters. They will be sent to the server along with the request.
Map<String, Object> queryParams = new HashMap<>();
queryParams.put("param1", 2);
try (QueryResponse response =
client.query("SELECT * FROM " + table + " WHERE col1 >= {param1:UInt32}", queryParams, new QuerySettings()).get()) {
// Create a reader to access the data in a convenient way
ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);
while (reader.hasNext()) {
reader.next(); // Read the next record from stream and parse it
// reading data
}
} catch (Exception e) {
log.error("Failed to read data", e);
}queryAll(String sqlQuery)
Запрашивает данные в формате RowBinaryWithNamesAndTypes. Возвращает результат в виде коллекции. Производительность чтения аналогична reader, однако для хранения всего набора данных требуется больше памяти.
Подписи
List<GenericRecord> queryAll(String sqlQuery)Параметры
sqlQuery — SQL-выражение для запроса данных на сервере.
Возвращаемое значение
Полный набор данных, представленный в виде списка объектов GenericRecord, обеспечивающих построчный доступ к результирующим данным.
Примеры
try {
log.info("Reading whole table and process record by record");
final String sql = "select * from " + TABLE_NAME + " where title <> ''";
// Read whole result set and process it record by record
client.queryAll(sql).forEach(row -> {
double id = row.getDouble("id");
String title = row.getString("title");
String url = row.getString("url");
log.info("id: {}, title: {}, url: {}", id, title, url);
});
} catch (Exception e) {
log.error("Failed to read data", e);
}QuerySettings
Параметры конфигурации для операций с запросами.
Методы конфигурации
| Метод | Описание |
|---|---|
setQueryId(String queryId) |
Устанавливает Query id, который будет присвоен операции. |
setFormat(ClickHouseFormat format) |
Задает формат ответа. Полный список см. в RowBinaryWithNamesAndTypes. |
setMaxExecutionTime(Integer maxExecutionTime) |
Устанавливает время выполнения операции на сервере. Не влияет на тайм-аут чтения. |
waitEndOfQuery(Boolean waitEndOfQuery) |
Указывает серверу дождаться завершения запроса перед отправкой ответа. |
setUseServerTimeZone(Boolean useServerTimeZone) |
Часовой пояс сервера (см. конфигурацию клиента) будет использоваться для разбора типов date/time в результате операции. По умолчанию — false. |
setUseTimeZone(String timeZone) |
Просит сервер использовать timeZone для преобразования времени. См. session_timezone. |
serverSetting(String name, String value) |
Устанавливает отдельные настройки сервера для операции. |
serverSetting(String name, Collection values) |
Устанавливает отдельные настройки сервера с несколькими значениями для операции. Элементы коллекции должны иметь тип String. |
setDBRoles(Collection dbRoles) |
Задает роли БД, которые будут установлены перед выполнением операции. Элементы коллекции должны быть строковыми значениями String. |
setOption(String option, Object value) |
Задаёт параметр конфигурации в исходном формате. Это не настройка сервера. |
QueryResponse
Объект ответа, содержащий результат выполнения запроса. Доступен только в том случае, если клиент получил ответ от сервера.
| Метод | Описание |
|---|---|
ClickHouseFormat getFormat() |
Возвращает формат, в котором кодируются данные ответа. |
InputStream getInputStream() |
Возвращает несжатый поток байтов с данными в указанном формате. |
OperationMetrics getMetrics() |
Возвращает объект, содержащий метрики операции. |
String getQueryId() |
Возвращает Query id, назначенный операции приложением (через настройки операции) или сервером. |
TimeZone getTimeZone() |
Возвращает часовой пояс, который следует использовать для обработки типов Date/DateTime в ответе. |
Примеры
- Пример кода доступен в репозитории
- Справочник по Spring Service реализации
Общий API
getTableSchema(String table)
Загружает схему таблицы для table.
Сигнатуры
TableSchema getTableSchema(String table)
TableSchema getTableSchema(String table, String database)Параметры
table - имя таблицы, для которой нужно получить данные схемы.
database — база данных, в которой определена целевая таблица.
Возвращаемое значение
Возвращает объект TableSchema со списком столбцов таблицы.
getTableSchemaFromQuery(String sql)
Извлекает схему из SQL-оператора.
Сигнатуры
TableSchema getTableSchemaFromQuery(String sql)Параметры
sql - оператор SQL "SELECT", схему которого необходимо вернуть.
Возвращаемое значение
Возвращает объект TableSchema со столбцами, соответствующими выражению sql.
TableSchema
register(Class<?> clazz, TableSchema schema)
Компилирует слой сериализации и десериализации для Java-класса, используемого при записи/чтении данных с помощью schema. Метод создаёт сериализатор и десериализатор для пары геттер/сеттер и соответствующего столбца.
Соответствие столбца определяется путём извлечения его имени из имени метода. Например, getFirstName будет соответствовать столбцу first_name или firstname.
Сигнатуры
void register(Class<?> clazz, TableSchema schema)Параметры
clazz — класс, представляющий POJO, используемый для чтения/записи данных.
schema — схема данных для сопоставления со свойствами POJO.
Примеры
client.register(ArticleViewEvent.class, client.getTableSchema(TABLE_NAME));Примеры использования
Полный код примеров хранится в репозитории в папке 'example`:
- client-v2 — основной набор примеров.
- demo-service — пример использования клиента в приложении Spring Boot.
- demo-kotlin-service — пример использования клиента в приложении на Ktor (Kotlin).
Чтение данных
Есть два распространённых способа чтения данных:
- метод
query(), который возвращает низкоуровневый объектQueryResponse, содержащийInputStreamс данными. Обычно используется вместе сClickHouseBinaryFormatReaderдля потокового чтения, но может использоваться и с любой другой пользовательской реализацией ридера.QueryResponseтакже предоставляет доступ к метаданным результирующего набора и метрикам. - Метод
queryAll()и использованиеGenericRecordдля удобного доступа к строкам. В этом случае весь результирующий набор загружается в память. - Метод
queryRecords(), который возвращаетcom.clickhouse.client.api.query.Records, — это итератор по объектамGenericRecord. Этот метод использует потоковый подход (данные не загружаются в память) иGenericRecordдля доступа к данным.
Примечание: стриминговый подход требует быстрого чтения данных, иначе может возникнуть тайм-аут записи на сервере, так как данные считываются напрямую из сетевого потока.
Чтение массивов
Методы ClickHouseBinaryFormatReader
getList(...)— читает любойArray(...)какList<T>. Хороший вариант по умолчанию для чтения с гибкой типизацией. Поддерживает вложенные массивы.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)— лучше всего подходят для одномерных массивов значений, совместимых с примитивными типами.getStringArray(...)— дляArray(String)(и значенийenum, представленных в виде имён).getObjectArray(...)— универсальный вариант дляArray(...)с любым типом элементов, включая вложенные массивы. Используйте для чтения массивов с Nullable-значениями и вложенных массивов.
Для всех методов доступны перегрузки по индексу и по имени. Индексация начинается с 1. Перегрузки по индексу обеспечивают прямой доступ к столбцу. Методы по имени требуют поиска по индексу при каждом обращении.
try (QueryResponse response = client.query("SELECT * FROM my_table").get()) {
ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);
while (reader.next() != null) {
Object[] uint64 = reader.getObjectArray("uint64_arr"); // Array(UInt64) -> BigInteger[]
Object[] arr2d = reader.getObjectArray("arr2d"); // Array(Array(Int64)) -> Object[]
// nested arrays are returned as nested Object[]:
Object[] firstInner = (Object[]) arr2d[0];
Long firstValue = (Long) firstInner[0];
}
}Методы GenericRecord
getList(...)— читает любойArray(...)какList<T>. Хороший вариант по умолчанию для чтения с гибкой типизацией. Поддерживает вложенные массивы.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)— лучше всего подходят для одномерных массивов значений, совместимых с примитивными типами.getStringArray(...)— дляArray(String)(и значенийenum, представленных в виде имён).getObjectArray(...)— универсальный вариант дляArray(...)с любым типом элементов, включая вложенные массивы. Используйте для чтения массивов с Nullable-значениями и вложенных массивов.
Для всех методов доступны перегрузки по индексу и по имени. Индексация начинается с 1. Перегрузки по индексу обеспечивают прямой доступ к столбцу. Методы по имени требуют поиска по индексу при каждом обращении.
try (QueryResponse response = client.query("SELECT * FROM my_table").get()) {
List<GenericRecord> rows = client.queryAll(
"SELECT int_arr, arr2d_nullable FROM test_arrays ORDER BY id");
for (GenericRecord row : rows) {
Object[] intArr = row.getObjectArray("int_arr"); // Array(Int32) -> Integer[]
Object[] arr2d = row.getObjectArray("arr2d_nullable"); // Array(Array(Nullable(Int32)))
Object[] inner = (Object[]) arr2d[0];
Object maybeNull = inner[1]; // may be null
}
}Руководство по миграции
Старый клиент (V1) использовал com.clickhouse.client.ClickHouseClient#builder в качестве точки входа. Новый клиент (V2) использует аналогичный подход с com.clickhouse.client.api.Client.Builder. Основные
отличия:
- Для получения реализации service loader не используется.
com.clickhouse.client.api.Client— это класс-фасад для любых реализаций, которые могут появиться в будущем. - меньше источников конфигурации: один передаётся билдеру, а другой — через настройки операции (
QuerySettings,InsertSettings). В предыдущей версии конфигурация задавалась для каждого узла, а в некоторых случаях также загружались переменные окружения.
Соответствие параметров конфигурации
В V1 есть 3 класса enum, связанных с конфигурацией:
com.clickhouse.client.config.ClickHouseDefaults— параметры конфигурации, которые обычно задаются в большинстве случаев. Например,USERиPASSWORD.com.clickhouse.client.config.ClickHouseClientOption— параметры конфигурации, относящиеся непосредственно к клиенту. Например,HEALTH_CHECK_INTERVAL.com.clickhouse.client.http.config.ClickHouseHttpOption— параметры конфигурации, характерные для HTTP-интерфейса. Например,RECEIVE_QUERY_PROGRESS.
Они были разработаны для группировки параметров и обеспечения чёткого разделения. Однако в некоторых случаях это приводило к путанице (например, есть ли разница между com.clickhouse.client.config.ClickHouseDefaults#ASYNC и
com.clickhouse.client.config.ClickHouseClientOption#ASYNC). Новый клиент V2 использует com.clickhouse.client.api.Client.Builder как единый словарь всех возможных параметров конфигурации клиента. В классе
com.clickhouse.client.api.ClientConfigProperties перечислены все имена параметров конфигурации.
В таблице ниже показано, какие старые параметры поддерживаются в новом клиенте и что они означают теперь.
Обозначения: ✔ = поддерживается, ✗ = удалено
| Конфигурация V1 | Метод Builder в V2 | Комментарии |
|---|---|---|
ClickHouseDefaults#HOST |
Client.Builder#addEndpoint |
|
ClickHouseDefaults#PROTOCOL |
✗ | В V2 поддерживается только HTTP |
ClickHouseDefaults#DATABASEClickHouseClientOption#DATABASE |
Client.Builder#setDefaultDatabase |
|
ClickHouseDefaults#USER |
Client.Builder#setUsername |
|
ClickHouseDefaults#PASSWORD |
Client.Builder#setPassword |
|
ClickHouseClientOption#CONNECTION_TIMEOUT |
Client.Builder#setConnectTimeout |
|
ClickHouseClientOption#CONNECTION_TTL |
Client.Builder#setConnectionTTL |
|
ClickHouseHttpOption#MAX_OPEN_CONNECTIONS |
Client.Builder#setMaxConnections |
|
ClickHouseHttpOption#KEEP_ALIVEClickHouseHttpOption#KEEP_ALIVE_TIMEOUT |
Client.Builder#setKeepAliveTimeout |
|
ClickHouseHttpOption#CONNECTION_REUSE_STRATEGY |
Client.Builder#setConnectionReuseStrategy |
|
ClickHouseHttpOption#USE_BASIC_AUTHENTICATION |
Client.Builder#useHTTPBasicAuth |
| Конфигурация V1 | Метод Builder | Комментарии |
|---|---|---|
ClickHouseDefaults#SSL_CERTIFICATE_TYPE |
✗ | |
ClickHouseDefaults#SSL_KEY_ALGORITHM |
✗ | |
ClickHouseDefaults#SSL_PROTOCOL |
✗ | |
ClickHouseClientOption#SSL |
✗ | См. Client.Builder#addEndpoint |
ClickHouseClientOption#SSL_MODE |
✗ | |
ClickHouseClientOption#SSL_ROOT_CERTIFICATE |
Client.Builder#setRootCertificate |
SSL-аутентификация должна быть включена через useSSLAuthentication |
ClickHouseClientOption#SSL_CERTIFICATE |
Client.Builder#setClientCertificate |
|
ClickHouseClientOption#SSL_KEY |
Client.Builder#setClientKey |
|
ClickHouseClientOption#KEY_STORE_TYPE |
Client.Builder#setSSLTrustStoreType |
|
ClickHouseClientOption#TRUST_STORE |
Client.Builder#setSSLTrustStore |
|
ClickHouseClientOption#KEY_STORE_PASSWORD |
Client.Builder#setSSLTrustStorePassword |
|
ClickHouseClientOption#SSL_SOCKET_SNI |
Client.Builder#sslSocketSNI |
|
ClickHouseClientOption#CUSTOM_SOCKET_FACTORY |
✗ | |
ClickHouseClientOption#CUSTOM_SOCKET_FACTORY_OPTIONS |
✗ | См. Client.Builder#sslSocketSNI для настройки SNI |
| Конфигурация V1 | Метод построителя V2 | Комментарии |
|---|---|---|
ClickHouseClientOption#SOCKET_TIMEOUT |
Client.Builder#setSocketTimeout |
|
ClickHouseClientOption#SOCKET_REUSEADDR |
Client.Builder#setSocketReuseAddress |
|
ClickHouseClientOption#SOCKET_KEEPALIVE |
Client.Builder#setSocketKeepAlive |
|
ClickHouseClientOption#SOCKET_LINGER |
Client.Builder#setSocketLinger |
|
ClickHouseClientOption#SOCKET_IP_TOS |
✗ | |
ClickHouseClientOption#SOCKET_TCP_NODELAY |
Client.Builder#setSocketTcpNodelay |
|
ClickHouseClientOption#SOCKET_RCVBUF |
Client.Builder#setSocketRcvbuf |
|
ClickHouseClientOption#SOCKET_SNDBUF |
Client.Builder#setSocketSndbuf |
| Конфигурация V1 | Метод Builder V2 | Комментарии |
|---|---|---|
ClickHouseClientOption#COMPRESS |
Client.Builder#compressServerResponse |
См. также useHttpCompression |
ClickHouseClientOption#DECOMPRESS |
Client.Builder#compressClientRequest |
См. также useHttpCompression |
ClickHouseClientOption#COMPRESS_ALGORITHM |
✗ | LZ4 для не-HTTP. Для HTTP используется Accept-Encoding |
ClickHouseClientOption#DECOMPRESS_ALGORITHM |
✗ | LZ4 для не-HTTP. Для HTTP используется Content-Encoding |
ClickHouseClientOption#COMPRESS_LEVEL |
✗ | |
ClickHouseClientOption#DECOMPRESS_LEVEL |
✗ |
| Конфигурация V1 | Метод построителя V2 | Комментарии |
|---|---|---|
ClickHouseClientOption#PROXY_TYPE |
Client.Builder#addProxy |
|
ClickHouseClientOption#PROXY_HOST |
Client.Builder#addProxy |
|
ClickHouseClientOption#PROXY_PORT |
Client.Builder#addProxy |
|
ClickHouseClientOption#PROXY_USERNAME |
Client.Builder#setProxyCredentials |
|
ClickHouseClientOption#PROXY_PASSWORD |
Client.Builder#setProxyCredentials |
| Конфигурация V1 | Метод построителя V2 | Комментарии |
|---|---|---|
ClickHouseClientOption#MAX_EXECUTION_TIME |
Client.Builder#setExecutionTimeout |
|
ClickHouseClientOption#RETRY |
Client.Builder#setMaxRetries |
См. также retryOnFailures |
ClickHouseHttpOption#AHC_RETRY_ON_FAILURE |
Client.Builder#retryOnFailures |
|
ClickHouseClientOption#FAILOVER |
✗ | |
ClickHouseClientOption#REPEAT_ON_SESSION_LOCK |
✗ | |
ClickHouseClientOption#SESSION_ID |
✗ | |
ClickHouseClientOption#SESSION_CHECK |
✗ | |
ClickHouseClientOption#SESSION_TIMEOUT |
✗ |
| Конфигурация V1 | Метод Builder в V2 | Комментарии |
|---|---|---|
ClickHouseDefaults#SERVER_TIME_ZONEClickHouseClientOption#SERVER_TIME_ZONE |
Client.Builder#setServerTimeZone |
|
ClickHouseClientOption#USE_SERVER_TIME_ZONE |
Client.Builder#useServerTimeZone |
|
ClickHouseClientOption#USE_SERVER_TIME_ZONE_FOR_DATES |
||
ClickHouseClientOption#USE_TIME_ZONE |
Client.Builder#useTimeZone |
| Конфигурация V1 | Метод Builder V2 | Комментарии |
|---|---|---|
ClickHouseClientOption#BUFFER_SIZE |
Client.Builder#setClientNetworkBufferSize |
|
ClickHouseClientOption#BUFFER_QUEUE_VARIATION |
✗ | |
ClickHouseClientOption#READ_BUFFER_SIZE |
✗ | |
ClickHouseClientOption#WRITE_BUFFER_SIZE |
✗ | |
ClickHouseClientOption#REQUEST_CHUNK_SIZE |
✗ | |
ClickHouseClientOption#REQUEST_BUFFERING |
✗ | |
ClickHouseClientOption#RESPONSE_BUFFERING |
✗ | |
ClickHouseClientOption#MAX_BUFFER_SIZE |
✗ | |
ClickHouseClientOption#MAX_QUEUED_BUFFERS |
✗ | |
ClickHouseClientOption#MAX_QUEUED_REQUESTS |
✗ | |
ClickHouseClientOption#REUSE_VALUE_WRAPPER |
✗ |
| Конфигурация V1 | Метод Builder в V2 | Комментарии |
|---|---|---|
ClickHouseDefaults#ASYNCClickHouseClientOption#ASYNC |
Client.Builder#useAsyncRequests |
|
ClickHouseDefaults#MAX_SCHEDULER_THREADS |
✗ | см. setSharedOperationExecutor |
ClickHouseDefaults#MAX_THREADS |
✗ | см. setSharedOperationExecutor |
ClickHouseDefaults#THREAD_KEEPALIVE_TIMEOUT |
см. setSharedOperationExecutor |
|
ClickHouseClientOption#MAX_THREADS_PER_CLIENT |
✗ | |
ClickHouseClientOption#MAX_CORE_THREAD_TTL |
✗ |
| Конфигурация V1 | Метод построителя V2 | Комментарии |
|---|---|---|
ClickHouseHttpOption#CUSTOM_HEADERS |
Client.Builder#httpHeaders |
|
ClickHouseHttpOption#CUSTOM_PARAMS |
✗ | См. Client.Builder#serverSetting |
ClickHouseClientOption#CLIENT_NAME |
Client.Builder#setClientName |
|
ClickHouseHttpOption#CONNECTION_PROVIDER |
✗ | |
ClickHouseHttpOption#DEFAULT_RESPONSE |
✗ | |
ClickHouseHttpOption#SEND_HTTP_CLIENT_ID |
✗ | |
ClickHouseHttpOption#AHC_VALIDATE_AFTER_INACTIVITY |
✗ | Всегда включен при использовании Apache Http Client |
| Конфигурация V1 | Метод Builder в V2 | Комментарии |
|---|---|---|
ClickHouseDefaults#FORMATClickHouseClientOption#FORMAT |
✗ | Перенесено в настройки операций (QuerySettings и InsertSettings) |
ClickHouseClientOption#QUERY_ID |
✗ | См. QuerySettings и InsertSettings |
ClickHouseClientOption#LOG_LEADING_COMMENT |
✗ | См. QuerySettings#logComment и InsertSettings#logComment |
ClickHouseClientOption#MAX_RESULT_ROWS |
✗ | Настройка на стороне сервера |
ClickHouseClientOption#RESULT_OVERFLOW_MODE |
✗ | Настройка на стороне сервера |
ClickHouseHttpOption#RECEIVE_QUERY_PROGRESS |
✗ | Настройка на стороне сервера |
ClickHouseHttpOption#WAIT_END_OF_QUERY |
✗ | Настройка на стороне сервера |
ClickHouseHttpOption#REMEMBER_LAST_SET_ROLES |
Client#setDBRoles |
Теперь настраивается во время выполнения. См. также QuerySettings#setDBRoles и InsertSettings#setDBRoles |
| Конфигурация V1 | Метод построителя V2 | Комментарии |
|---|---|---|
ClickHouseClientOption#AUTO_DISCOVERY |
✗ | |
ClickHouseClientOption#LOAD_BALANCING_POLICY |
✗ | |
ClickHouseClientOption#LOAD_BALANCING_TAGS |
✗ | |
ClickHouseClientOption#HEALTH_CHECK_INTERVAL |
✗ | |
ClickHouseClientOption#HEALTH_CHECK_METHOD |
✗ | |
ClickHouseClientOption#NODE_DISCOVERY_INTERVAL |
✗ | |
ClickHouseClientOption#NODE_DISCOVERY_LIMIT |
✗ | |
ClickHouseClientOption#NODE_CHECK_INTERVAL |
✗ | |
ClickHouseClientOption#NODE_GROUP_SIZE |
✗ | |
ClickHouseClientOption#CHECK_ALL_NODES |
✗ |
| Конфигурация V1 | Метод построителя V2 | Комментарии |
|---|---|---|
ClickHouseDefaults#AUTO_SESSION |
✗ | Вопрос поддержки сеансов будет пересмотрен |
ClickHouseDefaults#BUFFERING |
✗ | |
ClickHouseDefaults#MAX_REQUESTS |
✗ | |
ClickHouseDefaults#ROUNDING_MODE |
||
ClickHouseDefaults#SERVER_VERSIONClickHouseClientOption#SERVER_VERSION |
Client.Builder#setServerVersion |
|
ClickHouseDefaults#SRV_RESOLVE |
✗ | |
ClickHouseClientOption#CUSTOM_SETTINGS |
||
ClickHouseClientOption#PRODUCT_NAME |
✗ | Используйте имя клиента |
ClickHouseClientOption#RENAME_RESPONSE_COLUMN |
✗ | |
ClickHouseClientOption#SERVER_REVISION |
✗ | |
ClickHouseClientOption#TRANSACTION_TIMEOUT |
✗ | |
ClickHouseClientOption#WIDEN_UNSIGNED_TYPES |
✗ | |
ClickHouseClientOption#USE_BINARY_STRING |
✗ | |
ClickHouseClientOption#USE_BLOCKING_QUEUE |
✗ | |
ClickHouseClientOption#USE_COMPILATION |
✗ | |
ClickHouseClientOption#USE_OBJECTS_IN_ARRAYS |
✗ | |
ClickHouseClientOption#MAX_MAPPER_CACHE |
✗ | |
ClickHouseClientOption#MEASURE_REQUEST_TIME |
✗ |
Общие различия
- Клиент V2 использует меньше проприетарных классов, что повышает переносимость. Например, V2 работает с любой реализацией
java.io.InputStreamдля записи данных на сервер. - Настройка
asyncв Client V2 по умолчанию имеет значениеoff. Это означает отсутствие дополнительных потоков и больший контроль приложения над клиентом. Для большинства сценариев использования эта настройка должна оставатьсяoff. При включенииasyncдля запроса создаётся отдельный поток. Это имеет смысл только при использовании исполнителя, управляемого приложением (см.com.clickhouse.client.api.Client.Builder#setSharedOperationExecutor)
Запись данных
- используйте любую реализацию
java.io.InputStream. V1com.clickhouse.data.ClickHouseInputStreamподдерживается, но использовать её НЕ рекомендуется. - Как только обнаруживается конец входного потока, он обрабатывается соответствующим образом. Перед этим необходимо закрыть выходной поток запроса.
V1: вставка данных в формате TSV.
InputStream inData = getInData();
ClickHouseRequest.Mutation request = client.read(server)
.write()
.table(tableName)
.format(ClickHouseFormat.TSV);
ClickHouseConfig config = request.getConfig();
CompletableFuture<ClickHouseResponse> future;
try (ClickHousePipedOutputStream requestBody = ClickHouseDataStreamFactory.getInstance()
.createPipedOutputStream(config)) {
// start the worker thread which transfer data from the input into ClickHouse
future = request.data(requestBody.getInputStream()).execute();
// Copy data from inData stream to requestBody stream
// We need to close the stream before getting a response
requestBody.close();
try (ClickHouseResponse response = future.get()) {
ClickHouseResponseSummary summary = response.getSummary();
Assert.assertEquals(summary.getWrittenRows(), numRows, "Num of written rows");
}
}V2 Вставка данных в формате TSV.
InputStream inData = getInData();
InsertSettings settings = new InsertSettings().setInputStreamCopyBufferSize(8198 * 2); // set copy buffer size
try (InsertResponse response = client.insert(tableName, inData, ClickHouseFormat.TSV, settings).get(30, TimeUnit.SECONDS)) {
// Insert is complete at this point
} catch (Exception e) {
// Handle exception
}- нужно вызвать только один метод. Нет необходимости создавать дополнительный объект запроса.
- Поток с телом запроса автоматически закрывается после копирования всех данных.
- Доступен новый низкоуровневый API
com.clickhouse.client.api.Client#insert(java.lang.String, java.util.List<java.lang.String>, com.clickhouse.client.api.DataStreamWriter, com.clickhouse.data.ClickHouseFormat, com.clickhouse.client.api.insert.InsertSettings).com.clickhouse.client.api.DataStreamWriterпредназначен для реализации пользовательской логики записи данных. Например, для чтения данных из очереди.
Чтение данных
- По умолчанию данные читаются в формате
RowBinaryWithNamesAndTypes. Сейчас при необходимости привязки данных поддерживается только этот формат. - Данные можно считать как набор записей с помощью метода
List<GenericRecord> com.clickhouse.client.api.Client#queryAll(java.lang.String). Он считывает данные в память и закрывает соединение. Никакой дополнительной обработки не требуется.GenericRecordпредоставляет доступ к данным и поддерживает некоторые преобразования.
Collection<GenericRecord> records = client.queryAll("SELECT * FROM table");
for (GenericRecord record : records) {
int rowId = record.getInteger("rowID");
String name = record.getString("name");
LocalDateTime ts = record.getLocalDateTime("ts");
}Библиотека Java-клиента для взаимодействия с сервером БД через его протоколы. Текущая реализация поддерживает только HTTP-интерфейс. Библиотека предоставляет собственный API для отправки запросов на сервер.
Настройка
<!-- https://mvnrepository.com/artifact/com.clickhouse/clickhouse-http-client -->
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-http-client</artifactId>
<version>0.7.2</version>
</dependency>// https://mvnrepository.com/artifact/com.clickhouse/clickhouse-http-client
implementation("com.clickhouse:clickhouse-http-client:0.7.2")// https://mvnrepository.com/artifact/com.clickhouse/clickhouse-http-client
implementation 'com.clickhouse:clickhouse-http-client:0.7.2'Начиная с версии 0.5.0, драйвер использует новую клиентскую HTTP-библиотеку, которую необходимо добавить как зависимость.
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>// https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5
implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")// https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5
implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1'Инициализация
Формат URL-адреса подключения: protocol://host[:port][/database][?param[=value][¶m[=value]][#tag[,tag]], например:
http://localhost:8443?ssl=true&sslmode=NONEhttps://(https://explorer@play.clickhouse.com:443
Подключение к одному узлу:
ClickHouseNode server = ClickHouseNode.of("http://localhost:8123/default?compress=0");Подключение к кластеру с несколькими узлами:
ClickHouseNodes servers = ClickHouseNodes.of(
"jdbc:ch:http://server1.domain,server2.domain,server3.domain/my_db"
+ "?load_balancing_policy=random&health_check_interval=5000&failover=2");API запросов
try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
ClickHouseResponse response = client.read(servers)
.format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
.query("select * from numbers limit :limit")
.params(1000)
.executeAndWait()) {
ClickHouseResponseSummary summary = response.getSummary();
long totalRows = summary.getTotalRowsToRead();
}API стриминговых запросов
try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
ClickHouseResponse response = client.read(servers)
.format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
.query("select * from numbers limit :limit")
.params(1000)
.executeAndWait()) {
for (ClickHouseRecord r : response.records()) {
int num = r.getValue(0).asInteger();
// преобразование типов
String str = r.getValue(0).asString();
LocalDate date = r.getValue(0).asDate();
}
}См. полный пример кода в репозитории.
API вставки
try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
ClickHouseResponse response = client.read(servers).write()
.format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
.query("insert into my_table select c2, c3 from input('c1 UInt8, c2 String, c3 Int32')")
.data(myInputStream) // `myInputStream` — источник данных в формате RowBinary
.executeAndWait()) {
ClickHouseResponseSummary summary = response.getSummary();
summary.getWrittenRows();
}См. полный пример кода в репозитории.
Кодирование RowBinary
Формат RowBinary описан на соответствующей странице.
Пример кода приведён здесь.
Возможности
Сжатие
По умолчанию клиент будет использовать сжатие LZ4, для которого требуется следующая зависимость:
<!-- https://mvnrepository.com/artifact/org.lz4/lz4-java -->
<dependency>
<groupId>org.lz4</groupId>
<artifactId>lz4-java</artifactId>
<version>1.8.0</version>
</dependency>// https://mvnrepository.com/artifact/org.lz4/lz4-java
implementation("org.lz4:lz4-java:1.8.0")// https://mvnrepository.com/artifact/org.lz4/lz4-java
implementation 'org.lz4:lz4-java:1.8.0'Вы также можете использовать gzip, задав compress_algorithm=gzip в URL подключения.
Кроме того, сжатие можно отключить несколькими способами.
- Отключите это, указав
compress=0в URL подключения:http://localhost:8123/default?compress=0 - Отключите в конфигурации клиента:
ClickHouseClient client = ClickHouseClient.builder()
.config(new ClickHouseConfig(Map.of(ClickHouseClientOption.COMPRESS, false)))
.nodeSelector(ClickHouseNodeSelector.of(ClickHouseProtocol.HTTP))
.build();Подробнее о различных вариантах сжатия см. в документации по сжатию.
Несколько запросов
Выполнять несколько запросов в потоке-воркере подряд в рамках одного и того же сеанса:
CompletableFuture<List<ClickHouseResponseSummary>> future = ClickHouseClient.send(servers.apply(servers.getNodeSelector()),
"create database if not exists my_base",
"use my_base",
"create table if not exists test_table(s String) engine=Memory",
"insert into test_table values('1')('2')('3')",
"select * from test_table limit 1",
"truncate table test_table",
"drop table if exists test_table");
List<ClickHouseResponseSummary> results = future.get();Именованные параметры
Параметры можно передавать по имени, не полагаясь исключительно на их позицию в списке параметров. Эта возможность доступна с помощью функции params.
try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
ClickHouseResponse response = client.read(servers)
.format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
.query("select * from my_table where name=:name limit :limit")
.params("Ben", 1000)
.executeAndWait()) {
//...
}
}Обнаружение узлов
Java-клиент поддерживает автоматическое обнаружение узлов ClickHouse. По умолчанию эта функция отключена. Чтобы включить её вручную, задайте для auto_discovery значение true:
properties.setProperty("auto_discovery", "true");Или в URL подключения:
jdbc:ch://my-server/system?auto_discovery=trueЕсли автообнаружение включено, нет необходимости указывать все узлы ClickHouse в URL подключения. Узлы, указанные в URL, будут использоваться как seed-узлы, а Java-клиент автоматически обнаружит дополнительные узлы из системных таблиц и/или clickhouse-keeper или zookeeper.
Следующие параметры отвечают за настройку автоматического обнаружения:
| Свойство | По умолчанию | Описание |
|---|---|---|
| auto_discovery | false |
Должен ли клиент обнаруживать дополнительные узлы через системные таблицы и/или clickhouse-keeper/zookeeper. |
| node_discovery_interval | 0 |
Интервал обнаружения узлов в миллисекундах; нулевое или отрицательное значение означает однократное обнаружение. |
| node_discovery_limit | 100 |
Максимальное число узлов, которые можно обнаружить за один раз; нулевое или отрицательное значение означает, что ограничение отсутствует. |
Балансировка нагрузки
Java-клиент выбирает узел ClickHouse для отправки запросов согласно политике балансировки нагрузки. В общем случае политика балансировки нагрузки отвечает за следующее:
- Получить узел из списка управляемых узлов.
- Управление состоянием узла.
- При необходимости запланируйте выполнение фонового процесса для обнаружения узлов (если включено автообнаружение) и выполните проверку работоспособности.
Ниже приведён список параметров настройки балансировки нагрузки:
| Параметр | По умолчанию | Описание |
|---|---|---|
| load_balancing_policy | "" |
Политика балансировки нагрузки может быть одной из: firstAlive — запрос отправляется на первый доступный узел из списка управляемых узловrandom — запрос отправляется на случайный узел из списка управляемых узлов roundRobin — запрос по очереди отправляется на каждый узел из списка управляемых узлов.ClickHouseLoadBalancingPolicy — пользовательская политика балансировки нагрузки |
| load_balancing_tags | "" |
Теги балансировки нагрузки для фильтрации узлов. Запросы отправляются только на узлы с указанными тегами |
| health_check_interval | 0 |
Интервал проверки состояния в миллисекундах; нулевое или отрицательное значение означает однократную проверку. |
| health_check_method | ClickHouseHealthCheckMethod.SELECT_ONE |
Метод проверки работоспособности. Может быть одним из следующих: ClickHouseHealthCheckMethod.SELECT_ONE — проверка с помощью запроса select 1ClickHouseHealthCheckMethod.PING — проверка на уровне протокола, которая обычно выполняется быстрее |
| node_check_interval | 0 |
Интервал проверки узла в миллисекундах; отрицательное число считается равным нулю. Состояние узла проверяется, если с момента последней проверки прошло указанное количество времени. Разница между health_check_interval и node_check_interval заключается в том, что параметр health_check_interval планирует фоновую задачу, которая проверяет состояние списка узлов (всех или неисправных), а node_check_interval задаёт, сколько времени должно пройти с момента последней проверки конкретного узла |
| check_all_nodes | false |
Выполнять ли проверку состояния для всех узлов или только для неисправных. |
Переключение при отказе и повторные попытки
Java-клиент предоставляет параметры конфигурации для настройки поведения failover и retry при сбоях запросов:
| Свойство | По умолчанию | Описание |
|---|---|---|
| failover | 0 |
Максимальное число переключений при отказе для одного запроса. Нулевое или отрицательное значение означает, что переключение при отказе отключено. При переключении при отказе неудавшийся запрос отправляется на другой узел (в соответствии с политикой балансировки нагрузки), чтобы восстановить работоспособность после сбоя. |
| retry | 0 |
Максимальное количество повторных попыток для запроса. Нулевое или отрицательное значение означает, что повторные попытки не выполняются. Повторная попытка отправляет запрос на тот же узел и выполняется только в том случае, если ClickHouse server возвращает код ошибки NETWORK_ERROR |
| repeat_on_session_lock | true |
Следует ли повторять выполнение, пока сеанс заблокирован, до истечения тайм-аута (согласно session_timeout или connect_timeout). Неудачный запрос повторяется, если ClickHouse server возвращает код ошибки SESSION_IS_LOCKED |
Добавление пользовательских HTTP-заголовков
Java-клиент поддерживает транспортный уровень HTTP/S и позволяет добавлять пользовательские HTTP-заголовки к запросу.
Для этого используйте свойство custom_http_headers; заголовки перечисляются через ,. Ключ и значение заголовка разделяются символом =.
Поддержка Java-клиента
options.put("custom_http_headers", "X-ClickHouse-Quota=test, X-ClickHouse-Test=test");JDBC-драйвер
properties.setProperty("custom_http_headers", "X-ClickHouse-Quota=test, X-ClickHouse-Test=test");