JDBC-драйвер
clickhouse-jdbc реализует стандартный интерфейс JDBC с использованием последней версии Java-клиента.
Рекомендуется использовать последнюю версию Java-клиента напрямую, если критичны производительность или прямой доступ.
Требования к среде
- OpenJDK версии >= 8
Настройка
- Maven
- Gradle (Kotlin)
- Gradle
Конфигурация
Класс драйвера: com.clickhouse.jdbc.ClickHouseDriver
com.clickhouse.jdbc.ClickHouseDriver — это класс-фасад для новой и старой реализаций JDBC. По умолчанию используется новая реализация JDBC.
Чтобы использовать старую реализацию JDBC, установите свойство clickhouse.jdbc.v1 в значение true в параметрах подключения.
com.clickhouse.jdbc.Driver — новая реализация JDBC.
com.clickhouse.jdbc.DriverV1 — старая реализация JDBC.
Синтаксис URL: jdbc:(ch|clickhouse)[:<protocol>]://endpoint[:port][/<database>][?param1=value1¶m2=value2][#tag1,tag2,...], например:
jdbc:clickhouse:http://localhost:8123jdbc:clickhouse:https://localhost:8443?ssl=true
Обратите внимание на следующие особенности синтаксиса URL:
- в URL может быть указана только одна конечная точка
- протокол следует указывать, если используется протокол, отличный от протокола по умолчанию — 'HTTP'
- порт следует указывать, если используется не порт по умолчанию '8123'
- драйвер не пытается определять протокол по порту; его необходимо указывать явно
- Параметр
sslне нужен, если протокол указан.
Свойства соединения
Основные параметры конфигурации определены в Java-клиенте. Их следует передавать драйверу без изменений. Драйвер имеет собственные свойства, которые не входят в конфигурацию клиента; они перечислены ниже.
Свойства драйвера:
| Свойство | Значение по умолчанию | Описание |
|---|---|---|
disable_frameworks_detection | true | Отключить определение фреймворков по заголовку User-Agent |
jdbc_ignore_unsupported_values | false | Подавляет SQLFeatureNotSupportedException, если это не влияет на работу драйвера |
clickhouse.jdbc.v1 | false | Использовать старую реализацию JDBC вместо новой |
default_query_settings | null | Позволяет задавать настройки запроса по умолчанию для всех операций с запросами |
jdbc_resultset_auto_close | true | Автоматически закрывает ResultSet при закрытии объекта Statement |
beta.row_binary_for_simple_insert | false | Использовать реализацию PreparedStatement, основанную на записи в формате RowBinary. Работает только с запросами INSERT INTO ... VALUES. |
jdbc_resultset_auto_close | true | Автоматически закрывает ResultSet при закрытии объекта Statement |
jdbc_use_max_result_rows | false | Включает использование серверного свойства max_result_rows для ограничения количества строк, возвращаемых запросом. При включении переопределяет режим переполнения, установленный пользователем. Подробности см. в JavaDoc. |
jdbc_sql_parser | JAVACC | Определяет, какой SQL‑парсер будет использоваться. Доступные варианты: ANTLR4, ANTLR4_PARAMS_PARSER, JAVACC. |
Все настройки сервера должны иметь префикс clickhouse_setting_ (аналогично конфигурации клиента).
Пример конфигурации:
что будет эквивалентно следующему JDBC URL:
Примечание: URL-кодирование JDBC URL или свойств не требуется — они будут закодированы автоматически.
Поддерживаемые типы данных
Драйвер JDBC поддерживает те же форматы данных, что и базовый Java-клиент.
Сопоставление типов JDBC
Следующее сопоставление применяется к:
ResultSet#getObject(columnIndex)— этот метод вернёт объект соответствующего класса Java. (Int8->java.lang.Byte,Int16->java.lang.Shortи т. д.)ResultSetMetaData#getColumnType(columnIndex)— этот метод вернёт соответствующий тип JDBC. (Int8->java.lang.Byte,Int16->java.lang.Shortи т. д.)
Существует несколько способов изменить сопоставление:
- Метод
ResultSet#getObject(columnIndex, class)попытается преобразовать значение к типуclass. Для таких преобразований существуют некоторые ограничения. Подробности см. в соответствующих разделах.
Числовые типы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Int8 | TINYINT | java.lang.Byte |
| Int16 | SMALLINT | java.lang.Short |
| Int32 | INTEGER | java.lang.Integer |
| Int64 | BIGINT | java.lang.Long |
| Int128 | OTHER | java.math.BigInteger |
| Int256 | OTHER | java.math.BigInteger |
| UInt8 | OTHER | java.lang.Short |
| UInt16 | OTHER | java.lang.Integer |
| UInt32 | OTHER | java.lang.Long |
| UInt64 | OTHER | java.math.BigInteger |
| UInt128 | OTHER | java.math.BigInteger |
| UInt256 | OTHER | java.math.BigInteger |
| Float32 | REAL | java.lang.Float |
| Float64 | DOUBLE | java.lang.Double |
| Decimal32 | DECIMAL | java.math.BigDecimal |
| Decimal64 | DECIMAL | java.math.BigDecimal |
| Decimal128 | DECIMAL | java.math.BigDecimal |
| Decimal256 | DECIMAL | java.math.BigDecimal |
| Bool | BOOLEAN | java.lang.Boolean |
- Числовые типы можно свободно преобразовывать друг в друга. Поэтому значение
Int8можно получить какFloat64и наоборот.:rs.getObject(1, Float64.class)вернёт значение типаFloat64из столбцаInt8.rs.getLong(1)вернёт значение типаLongиз столбцаInt8.rs.getByte(1)может вернуть значение типаByteиз столбцаInt16, если его значение укладывается в диапазонByte.
- Преобразование из более широкого типа данных в более узкий не рекомендуется из‑за риска повреждения данных.
- Тип
Boolтакже ведёт себя как числовой. - Все числовые типы могут быть считаны как
java.lang.String.
Строковые типы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| String | VARCHAR | java.lang.String |
| FixedString | VARCHAR | java.lang.String |
Stringможет быть прочитан только какjava.lang.Stringилиbyte[].FixedStringсчитывается как есть и дополняется нулевыми байтами до длины столбца. (Например,FixedString(10)для'John'будет прочитан как'John\0\0\0\0\0\0\0\0\0'.)
Типы Enum
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Enum8 | OTHER | java.lang.String |
| Enum16 | OTHER | java.lang.String |
Enum8иEnum16по умолчанию сопоставляются сjava.lang.String.- Значения Enum могут быть прочитаны как числовые с помощью соответствующего числового геттера или метода
getObject(columnIndex, Integer.class). Enum16внутренне сопоставляется с типом short, аEnum8— с типом byte. Следует избегать чтения значенийEnum16как byte, так как это может привести к повреждению данных.- Значения Enum в
PreparedStatementможно указывать как строковые или числовые значения.
Типы даты и времени
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Date | DATE | java.sql.Date |
| Date32 | DATE | java.sql.Date |
| DateTime | TIMESTAMP | java.sql.Timestamp |
| DateTime64 | TIMESTAMP | java.sql.Timestamp |
| Time | TIME | java.sql.Time |
| Time64 | TIME | java.sql.Time |
- Типы Date / Time сопоставляются с типами
java.sqlдля лучшей совместимости с JDBC. Однако можно получить объектыjava.time.LocalDate,java.time.LocalDateTime,java.time.LocalTime, используяResultSet#getObject(columnIndex, Class<T>)и передав соответствующий класс в качестве второго аргумента.rs.getObject(1, java.time.LocalDate.class)вернёт значение типаjava.time.LocalDateиз столбцаDate.rs.getObject(1, java.time.LocalDateTime.class)вернёт значение типаjava.time.LocalDateTimeиз столбцаDateTime.rs.getObject(1, java.time.LocalTime.class)вернёт значение типаjava.time.LocalTimeиз столбцаTime.
Date,Date32,Time,Time64не зависят от часового пояса сервера.DateTime,DateTime64зависят от часового пояса сервера или сеанса.DateTimeиDateTime64можно получить какZonedDateTime, используяgetObject(colIndex, ZonedDateTime.class).
Типы коллекций
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Array | ARRAY | java.sql.Array |
| Tuple | OTHER | Object[] |
| Map | JAVA_OBJECT | java.util.Map |
Arrayпо умолчанию сопоставляется сjava.sql.Arrayдля совместимости с JDBC. Это также даёт больше информации о возвращаемом значении массива, что полезно для вывода типов.Arrayреализует методgetResultSet(), возвращающийjava.sql.ResultSetс тем же содержимым, что и исходный массив.- Типы коллекций не следует читать как
java.lang.String, поскольку это некорректный способ представления данных (например, в массиве строковые значения не заключаются в кавычки). Mapсопоставляется типуJAVA_OBJECT, так как значение можно прочитать только с помощью методаgetObject(columnIndex, Class<T>).Mapне являетсяjava.sql.Struct, потому что у него нет именованных столбцов.
Tupleсопоставляется сObject[], поскольку он может содержать элементы разных типов, а использованиеListнедопустимо.Tupleможно прочитать какArrayс помощью методаgetObject(columnIndex, Array.class). В этом случаеArray#baseTypeNameвернёт определение столбца типаTuple.
Геотипы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Point | OTHER | double[] |
| Ring | OTHER | double[][] |
| Polygon | OTHER | double[][][] |
| MultiPolygon | OTHER | double[][][][] |
Типы Nullable и LowCardinality
NullableиLowCardinality— это специальные типы-обёртки для других типов.Nullableвлияет на формат имён типов, возвращаемых вResultSetMetaData
Специальные типы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| UUID | OTHER | java.util.UUID |
| IPv4 | OTHER | java.net.Inet4Address |
| IPv6 | OTHER | java.net.Inet6Address |
| JSON | OTHER | java.lang.String |
| AggregateFunction | OTHER | (двоичное представление) |
| SimpleAggregateFunction | (тип-обёртка) | (класс-обёртка) |
UUIDне является типом, определённым стандартом JDBC. Однако он является частью JDK. По умолчанию методgetObject()возвращает значение типаjava.util.UUID.UUIDможно читать и записывать какStringс помощью методаgetObject(columnIndex, String.class).IPv4иIPv6не относятся к стандартным типам JDBC. Однако они входят в состав JDK. По умолчанию при вызове методаgetObject()возвращаются объекты типовjava.net.Inet4Addressиjava.net.Inet6Address.IPv4иIPv6можно читать и записывать в видеStringс помощью методаgetObject(columnIndex, String.class).
Обработка дат, времени и часовых поясов
java.sql.Date, java.sql.Time и java.sql.Timestamp могут усложнить вычисление часовых поясов — хотя они, разумеется, поддерживаются,
рекомендуется рассмотреть использование пакета java.time. ZonedDateTime и
OffsetDateTime являются отличной заменой для java.sql.Timestamp, java.sql.Date и java.sql.Time.
Date хранится без часового пояса, тогда как DateTime хранится с часовым поясом. Это может привести к неожиданным результатам при неосторожном использовании.
Создание соединения
Предоставление учётных данных и настроек
Простое выражение
Вставка данных
HikariCP
Дополнительная информация
Дополнительную информацию см. в нашем репозитории GitHub и документации Java-клиента.
Устранение неполадок
Логирование
Драйвер использует slf4j для ведения журнала и будет использовать первую доступную реализацию в classpath.
Устранение таймаута JDBC при больших вставках данных
При выполнении больших вставок в ClickHouse с длительным временем выполнения могут возникать ошибки тайм-аута JDBC, такие как:
Эти ошибки могут нарушить процесс вставки данных и повлиять на стабильность системы. Чтобы устранить эту проблему, может потребоваться настроить несколько параметров таймаута в операционной системе клиента.
macOS
В macOS можно настроить следующие параметры для решения проблемы:
net.inet.tcp.keepidle: 60000net.inet.tcp.keepintvl: 45000net.inet.tcp.keepinit: 45000net.inet.tcp.keepcnt: 8net.inet.tcp.always_keepalive: 1
Linux
В Linux одних только эквивалентных настроек может быть недостаточно для решения проблемы. Необходимы дополнительные действия из-за особенностей обработки параметров keep-alive для сокетов в Linux. Выполните следующие действия:
- Настройте следующие параметры ядра Linux в
/etc/sysctl.confили соответствующем конфигурационном файле:
net.inet.tcp.keepidle: 60000net.inet.tcp.keepintvl: 45000net.inet.tcp.keepinit: 45000net.inet.tcp.keepcnt: 8net.inet.tcp.always_keepalive: 1net.ipv4.tcp_keepalive_intvl: 75net.ipv4.tcp_keepalive_probes: 9net.ipv4.tcp_keepalive_time: 60 (можно рассмотреть уменьшение этого значения относительно значения по умолчанию (300 секунд))
- После изменения параметров ядра примените их, выполнив следующую команду:
После настройки этих параметров необходимо убедиться, что ваш клиент включает опцию Keep Alive для сокета:
Руководство по миграции
Основные изменения
| Возможность | V1 (устаревшая) | V2 (новая) |
|---|---|---|
| Поддержка транзакций | Частично поддерживается | Не поддерживается |
| Переименование столбцов в результирующем наборе | Частично поддерживается | Не поддерживается |
| SQL с несколькими операторами | Не поддерживается | Недоступно |
| Именованные параметры запроса | Поддерживается | Не поддерживается (отсутствует в спецификации JDBC) |
Потоковая передача данных с помощью PreparedStatement | Поддерживается | Не поддерживается |
- JDBC V2 реализован в более лёгком варианте, поэтому из него были удалены некоторые возможности.
- Потоковая передача данных не поддерживается в JDBC V2, так как она не входит ни в спецификацию JDBC, ни в стандарт Java.
- JDBC V2 требует явной конфигурации. Он не имеет настроек отказоустойчивости по умолчанию.
- Протокол должен явно указываться в URL. Не выполняется неявное определение протокола по номеру порта.
Изменения конфигурации
Доступны только два перечисления:
com.clickhouse.jdbc.DriverProperties— параметры конфигурации самого драйвера.com.clickhouse.client.api.ClientConfigProperties— свойства конфигурации клиента. Изменения конфигурации клиента описаны в документации по Java‑клиенту.
Свойства подключения разбираются следующим образом:
- Сначала из URL извлекаются свойства. Они имеют приоритет над всеми остальными свойствами.
- Свойства драйвера не передаются клиенту.
- Endpoints (host, port, protocol) извлекаются из URL.
Пример:
Изменения типов данных
Числовые типы
| Тип ClickHouse | Совместим с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Int8 | ✅ | TINYINT | java.lang.Byte | TINYINT | java.lang.Byte |
| Int16 | ✅ | SMALLINT | java.lang.Short | SMALLINT | java.lang.Short |
| Int32 | ✅ | INTEGER | java.lang.Integer | INTEGER | java.lang.Integer |
| Int64 | ✅ | BIGINT | java.lang.Long | BIGINT | java.lang.Long |
| Int128 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| Int256 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| UInt8 | ❌ | OTHER | java.lang.Short | OTHER | com.clickhouse.data.value.UnsignedByte |
| UInt16 | ❌ | OTHER | java.lang.Integer | OTHER | com.clickhouse.data.value.UnsignedShort |
| UInt32 | ❌ | OTHER | java.lang.Long | OTHER | com.clickhouse.data.value.UnsignedInteger |
| UInt64 | ❌ | OTHER | java.math.BigInteger | OTHER | com.clickhouse.data.value.UnsignedLong |
| UInt128 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| UInt256 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| Float32 | ✅ | REAL | java.lang.Float | REAL | java.lang.Float |
| Float64 | ✅ | DOUBLE | java.lang.Double | DOUBLE | java.lang.Double |
| Decimal32 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal64 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal128 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal256 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Bool | ✅ | BOOLEAN | java.lang.Boolean | BOOLEAN | java.lang.Boolean |
- Основное отличие заключается в том, что беззнаковые типы сопоставляются со стандартными типами Java, что повышает переносимость.
Строковые типы
| Тип в ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| String | ✅ | VARCHAR | java.lang.String | VARCHAR | java.lang.String |
| FixedString | ✅ | VARCHAR | java.lang.String | VARCHAR | java.lang.String |
FixedStringчитается «как есть» в обеих версиях. Например,FixedString(10)для'John'будет прочитан как'John\0\0\0\0\0\0\0\0\0'.- Когда используется
PreparedStatement#setBytes, значение будет преобразовано вunhex('<hex_string>'), а затем считано какString.
Типы даты и времени
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Date | ❌ | DATE | java.sql.Date | DATE | java.time.LocalDate |
| Date32 | ❌ | DATE | java.sql.Date | DATE | java.time.LocalDate |
| DateTime | ❌ | TIMESTAMP | java.sql.Timestamp | TIMESTAMP | java.time.OffsetDateTime |
| DateTime64 | ❌ | TIMESTAMP | java.sql.Timestamp | TIMESTAMP | java.time.OffsetDateTime |
| Time | ✅ | TIME | java.sql.Time | новый тип / не поддерживается | новый тип / не поддерживается |
| Time64 | ✅ | TIME | java.sql.Time | новый тип / не поддерживается | новый тип / не поддерживается |
TimeиTime64поддерживаются в V2 только как новые типы данных.DateTimeиDateTime64сопоставляются сjava.sql.Timestampдля обеспечения лучшей совместимости с JDBC.
Типы Enum
| Тип в ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Enum | ✅ | VARCHAR | java.lang.String | OTHER | java.lang.String |
| Enum8 | ✅ | VARCHAR | java.lang.String | OTHER | java.lang.String |
| Enum16 | ✅ | VARCHAR | java.lang.String | OTHER | java.lang.String |
Типы коллекций
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Array | ❌ | ARRAY | java.sql.Array | ARRAY | Object[] или массив примитивных типов |
| Tuple | ❌ | OTHER | Object[] | STRUCT | java.sql.Struct |
| Map | ❌ | JAVA_OBJECT | java.util.Map | STRUCT | java.util.Map |
- В V2
Arrayпо умолчанию сопоставляется сjava.sql.Arrayдля совместимости с JDBC. Это также позволяет получить больше информации о возвращаемом значении массива, что полезно для вывода типов. - В V2
Arrayреализует методgetResultSet(), который возвращает объектjava.sql.ResultSetс тем же содержимым, что и исходный массив. - V1 использует
STRUCTдляMap, но всегда возвращает объектjava.util.Map. V2 исправляет это, сопоставляяMapсJAVA_OBJECT. Кроме того,STRUCTявляется некорректным типом дляMap, поскольку вMapнет именованных столбцов. - V1 использует
STRUCTдляTuple, но всегда возвращает объектList<Object>. V2 исправляет это, сопоставляяTupleсOTHERи возвращаетObject[], поскольку использованиеListнекорректно: в кортеже могут присутствовать значения разных типов. - Методы
PreparedStatement#setBytesиResultSet#getBytesнельзя использовать с типами коллекций. Эти методы предназначены для работы с бинарными строками. - Обычно для записи и чтения типов
Arrayиспользуютjava.sql.Array. Драйвер JDBC полностью поддерживает такой способ работы.
Геотипы
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Point | ✅ | OTHER | double[] | OTHER | double[] |
| Ring | ✅ | OTHER | double[][] | OTHER | double[][] |
| Polygon | ✅ | OTHER | double[][][] | OTHER | double[][][] |
| MultiPolygon | ✅ | OTHER | double[][][][] | OTHER | double[][][][] |
Типы Nullable и LowCardinality
NullableиLowCardinality— это специальные типы-обёртки для других типов.- В V2 эти типы не изменялись.
Специальные типы
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| JSON | ❌ | OTHER | java.lang.String | не поддерживается | не поддерживается |
| AggregateFunction | ✅ | OTHER | (двоичное представление) | OTHER | (двоичное представление) |
| SimpleAggregateFunction | ✅ | (тип-обёртка) | (класс-обёртка) | (тип-обёртка) | (класс-обёртка) |
| UUID | ✅ | OTHER | java.util.UUID | VARCHAR | java.util.UUID |
| IPv4 | ✅ | OTHER | java.net.Inet4Address | VARCHAR | java.net.Inet4Address |
| IPv6 | ✅ | OTHER | java.net.Inet6Address | VARCHAR | java.net.Inet6Address |
| Dynamic | ❌ | OTHER | java.lang.Object | не поддерживается | не поддерживается |
| Variant | ❌ | OTHER | java.lang.Object | не поддерживается | не поддерживается |
- V1 использует
VARCHARдляUUID, но при этом всегда возвращает объектjava.util.UUID. V2 исправляет это, сопоставляяUUIDсOTHERи тоже возвращает объектjava.util.UUID. - V1 использует
VARCHARдляIPv4иIPv6, но всегда возвращает объектыjava.net.Inet4Addressиjava.net.Inet6Address. V2 исправляет это, сопоставляяIPv4иIPv6сOTHERи также возвращая объектыjava.net.Inet4Addressиjava.net.Inet6Address. DynamicиVariant— новые типы в V2. В V1 они не поддерживаются.- Тип
JSONоснован на типеDynamic. Поэтому он поддерживается только в V2. - Значения IPv4 и IPv6 можно считывать в виде массива байт (
byte[]), используя методgetBytes(columnIndex). Однако рекомендуется использовать специализированные для этих типов классы. - V2 не поддерживает чтение IP‑адресов как числовых значений, поскольку преобразование лучше реализовано в классах InetAddress.
Изменения метаданных базы данных
- V2 использует только термин
Schemaдля обозначения баз данных. ТерминCatalogзарезервирован для будущего использования. - V2 возвращает
falseдляDatabaseMetaData.supportsTransactions()иDatabaseMetaData.supportsSavepoints(). Это поведение будет изменено в последующих версиях.