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

Драйвер JDBC

примечание

clickhouse-jdbc реализует стандартный интерфейс JDBC, используя последний java-клиент. Мы рекомендуем использовать последний java-клиент напрямую, если производительность/прямой доступ критичны.

Изменения с 0.7.x

В версии 0.8 мы попытались сделать драйвер более строго соответствующим спецификации JDBC, поэтому некоторые функции были удалены, что может оказать на вас влияние:

Старая функцияПримечания
Поддержка транзакцийВ ранних версиях драйвера поддержка транзакций только имитировалась, что могло привести к неожиданным результатам.
Переименование колонок ответаResultSet был изменяемым - теперь они только для чтения для повышения эффективности
Поддержка многостStatement SQLПоддержка многозапросов только имитировалась, теперь она строго следует соотношению 1:1
Именованные параметрыНе часть спецификации JDBC
Подготовленный оператор на основе потокаРанняя версия драйвера позволяла использовать PreparedStatement вне JDBC - если вам нужны такие опции, мы рекомендуем ознакомиться с Java клиентом и его примерами.
примечание

Date хранится без временной зоны, в то время как DateTime хранится с временной зоной. Это может привести к неожиданным результатам, если вы не будете осторожны.

Требования к окружению

Настройка

<!-- https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc -->
<dependency>
    <groupId>com.clickhouse</groupId>
    <artifactId>clickhouse-jdbc</artifactId>
    <version>0.9.1</version>
    <classifier>shaded-all</classifier>
</dependency>

Конфигурация

Класс драйвера: com.clickhouse.jdbc.ClickHouseDriver

Синтаксис URL: jdbc:(ch|clickhouse)[:<protocol>]://endpoint1[,endpoint2,...][/<database>][?param1=value1&param2=value2][#tag1,tag2,...], например:

  • jdbc:clickhouse:http://localhost:8123
  • jdbc:clickhouse:https://localhost:8443?ssl=true

Свойства соединения:

В дополнение к стандартным свойствам JDBC, драйвер поддерживает свойства, специфичные для ClickHouse, предлагаемые подлежащим java клиентом. Где это возможно, методы будут возвращать SQLFeatureNotSupportedException, если функция не поддерживается. Другие пользовательские свойства включают:

СвойствоЗначение по умолчаниюОписание
disable_frameworks_detectiontrueОтключить обнаружение фреймворков для User-Agent
jdbc_ignore_unsupported_valuesfalseПодавляет SQLFeatureNotSupportedException
clickhouse.jdbc.v1falseИспользовать старую реализацию JDBC вместо новой JDBC
default_query_settingsnullПозволяет передавать настройки запросов по умолчанию с операциями запросов
jdbc_resultset_auto_closetrueАвтоматически закрывает ResultSet, когда закрыт Statement
beta.row_binary_for_simple_insertfalseИспользовать реализацию PreparedStatement на основе писателя RowBinary. Работает только для запросов INSERT INTO ... VALUES.

Поддерживаемые типы данных

JDBC драйвер поддерживает те же форматы данных, что и подлежащий java клиент.

Обработка дат, времени и временных зон

java.sql.Date, java.sql.Time и java.sql.Timestamp могут усложнить расчет временных зон - хотя они, конечно, поддерживаются, вы можете рассмотреть возможность использования пакета java.time. ZonedDateTime и OffsetDateTime являются отличными заменами для java.sql.Timestamp, java.sql.Date и java.sql.Time.

Создание соединения

String url = "jdbc:ch://my-server:8123/system";

Properties properties = new Properties();
DataSource dataSource = new DataSource(url, properties);//DataSource or DriverManager are the main entry points
try (Connection conn = dataSource.getConnection()) {
... // do something with the connection

Передача учетных данных и настроек

String url = "jdbc:ch://localhost:8123?jdbc_ignore_unsupported_values=true&socket_timeout=10";

Properties info = new Properties();
info.put("user", "default");
info.put("password", "password");
info.put("database", "some_db");

//Creating a connection with DataSource
DataSource dataSource = new DataSource(url, info);
try (Connection conn = dataSource.getConnection()) {
... // do something with the connection
}

//Alternate approach using the DriverManager
try (Connection conn = DriverManager.getConnection(url, info)) {
... // do something with the connection
}

Простой оператор


try (Connection conn = dataSource.getConnection(...);
    Statement stmt = conn.createStatement()) {
    ResultSet rs = stmt.executeQuery("select * from numbers(50000)");
    while(rs.next()) {
        // ...
    }
}

Вставка

try (PreparedStatement ps = conn.prepareStatement("INSERT INTO mytable VALUES (?, ?)")) {
    ps.setString(1, "test"); // id
    ps.setObject(2, LocalDateTime.now()); // timestamp
    ps.addBatch();
    ...
    ps.executeBatch(); // stream everything on-hand into ClickHouse
}

HikariCP

// connection pooling won't help much in terms of performance,
// because the underlying implementation has its own pool.
// for example: HttpURLConnection has a pool for sockets
HikariConfig poolConfig = new HikariConfig();
poolConfig.setConnectionTimeout(5000L);
poolConfig.setMaximumPoolSize(20);
poolConfig.setMaxLifetime(300_000L);
poolConfig.setDataSource(new ClickHouseDataSource(url, properties));

try (HikariDataSource ds = new HikariDataSource(poolConfig);
     Connection conn = ds.getConnection();
     Statement s = conn.createStatement();
     ResultSet rs = s.executeQuery("SELECT * FROM system.numbers LIMIT 3")) {
    while (rs.next()) {
        // handle row
        log.info("Integer: {}, String: {}", rs.getInt(1), rs.getString(1));//Same column but different types
    }
}

Дополнительная информация

Для получения дополнительной информации смотрите наш репозиторий на GitHub и документацию по Java клиенту.

Устранение неполадок

Логирование

Драйвер использует slf4j для логирования и будет использовать первую доступную реализацию в classpath.

Устранение таймаута JDBC при крупных вставках

При выполнении больших вставок в ClickHouse с длительным временем выполнения вы можете столкнуться с ошибками таймаута JDBC, такими как:

Caused by: java.sql.SQLException: Read timed out, server myHostname [uri=https://hostname.aws.clickhouse.cloud:8443]

Эти ошибки могут нарушать процесс вставки данных и влиять на стабильность системы. Чтобы решить эту проблему, вам может понадобиться отрегулировать несколько настроек таймаута в операционной системе клиента.

Mac OS

На Mac OS следующие настройки могут быть изменены для решения этой проблемы:

  • net.inet.tcp.keepidle: 60000
  • net.inet.tcp.keepintvl: 45000
  • net.inet.tcp.keepinit: 45000
  • net.inet.tcp.keepcnt: 8
  • net.inet.tcp.always_keepalive: 1

Linux

На Linux соответствующие настройки сами по себе могут не решить проблему. Требуются дополнительные шаги из-за различий в том, как Linux обрабатывает настройки keep-alive для сокетов. Следуйте этим шагам:

  1. Настройте следующие параметры ядра Linux в /etc/sysctl.conf или в связанном файле конфигурации:
  • net.inet.tcp.keepidle: 60000
  • net.inet.tcp.keepintvl: 45000
  • net.inet.tcp.keepinit: 45000
  • net.inet.tcp.keepcnt: 8
  • net.inet.tcp.always_keepalive: 1
  • net.ipv4.tcp_keepalive_intvl: 75
  • net.ipv4.tcp_keepalive_probes: 9
  • net.ipv4.tcp_keepalive_time: 60 (вы можете рассмотреть возможность уменьшения этого значения с 300 секунд по умолчанию)
  1. После изменения параметров ядра примените изменения, выполнив следующую команду:
sudo sysctl -p

После настройки этих параметров, вам нужно убедиться, что ваш клиент включает опцию Keep Alive для сокета:

properties.setProperty("socket_keepalive", "true");