メインコンテンツまでスキップ
メインコンテンツまでスキップ

JDBC ドライバー

注記

clickhouse-jdbc は最新の Java クライアントを使用して標準 JDBC インターフェースを実装しています。パフォーマンスや直接アクセスが重要な場合は、最新の Java クライアントを直接使用することをお勧めします。

0.7.x からの変更

0.8 では、ドライバーが JDBC 仕様により厳密に従うようにしたため、いくつかの機能が削除され、影響を受ける可能性があります:

古い機能メモ
トランザクションサポートドライバーの初期バージョンではトランザクションサポートをシミュレーションしていただけで、予期しない結果を引き起こす可能性があります。
レスポンスカラムのリネーミングResultSet は可変でしたが、効率のために現在は読み取り専用です。
マルチステートメント SQLマルチステートメントのサポートはシミュレーションされていましたが、現在は厳密に 1:1 に従います。
名付きパラメーターJDBC 仕様の一部ではありません。
ストリームベースの PreparedStatementドライバーの初期バージョンでは PreparedStatement の JDBC を介さない使用が許可されていました。こうしたオプションが必要な場合は、Java Client およびその を確認することをお勧めします。
注記

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 プロパティに加えて、ドライバーは基盤となる java client が提供する ClickHouse 特有のプロパティをサポートします。サポートされない機能に関しては、可能な限りメソッドが SQLFeatureNotSupportedException を返します。他のカスタムプロパティには次のようなものがあります:

プロパティデフォルト説明
disable_frameworks_detectiontrueUser-Agent のフレームワーク検出を無効にします
jdbc_ignore_unsupported_valuesfalseSQLFeatureNotSupportedException を抑制します
clickhouse.jdbc.v1false新しい JDBC の代わりに古い JDBC 実装を使用します
default_query_settingsnullクエリ操作にデフォルトのクエリ設定を渡すことを許可します
jdbc_resultset_auto_closetrueStatement が閉じられたときに ResultSet を自動的に閉じます
beta.row_binary_for_simple_insertfalseRowBinary ライターに基づいた PreparedStatement 実装を使用します。INSERT INTO ... VALUES クエリ専用です。

サポートされるデータ型

JDBC ドライバーは基盤となる java client と同じデータ形式をサポートします。

日付、時刻、およびタイムゾーンの取り扱い

java.sql.Datejava.sql.Time、および java.sql.Timestamp はタイムゾーンの計算を複雑にする可能性があります - もちろんサポートされていますが、java.time パッケージの使用を検討する価値があります。ZonedDateTimeOffsetDateTime は、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 Client ドキュメント をご覧ください。

トラブルシューティング

ロギング

ドライバーは slf4j を使用してロギングを行い、クラスパス上で最初に見つかった実装を使用します。

大きな挿入での JDBC タイムアウトの解決

ClickHouse で実行時間が長い大きな挿入を行うと、次のような JDBC タイムアウトエラーが発生することがあります:

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

これらのエラーはデータ挿入プロセスを妨げ、システムの安定性に影響を与えることがあります。この問題に対処するには、クライアントの OS でいくつかのタイムアウト設定を調整する必要があります。

macOS

macOS では、次の設定を調整して問題を解決できます:

  • 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 がソケットのキープアライブ設定を処理する方法の違いにより、追加の手順が必要です。次の手順に従ってください:

  1. /etc/sysctl.conf または関連する設定ファイルで次の Linux カーネルパラメータを調整します:
  • 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");