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

JDBC Driver

注記

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.8.2</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ドライバは、基盤となるJava Clientと同じデータフォーマットをサポートしています。

日付、時刻、およびタイムゾーンの処理

java.sql.Datejava.sql.Time、およびjava.sql.Timestampは、タイムゾーンの計算を複雑にする可能性がありますが、もちろんサポートされています。 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またはDriverManagerが主なエントリーポイントです
try (Connection conn = dataSource.getConnection()) {
... // 接続に対して何らかの処理を行う

資格情報と設定の提供

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");

//DataSourceを使って接続を作成する
DataSource dataSource = new DataSource(url, info);
try (Connection conn = dataSource.getConnection()) {
... // 接続に対して何らかの処理を行う
}

//DriverManagerを使用した別のアプローチ
try (Connection conn = DriverManager.getConnection(url, info)) {
... // 接続に対して何らかの処理を行う
}

シンプルステートメント


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()); // タイムスタンプ
    ps.addBatch();
    ...
    ps.executeBatch(); // すべてのデータをClickHouseにストリームする
}

HikariCP

// 接続プーリングはパフォーマンスにあまり寄与しません、
// なぜなら基盤となる実装自体がプールを持っているからです。
// 例えば: HttpURLConnection はソケット用にプールを持っています
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()) {
        // 行の処理
        log.info("整数: {}, 文字列: {}", rs.getInt(1), rs.getString(1));//同じカラムだが異なる型
    }
}

さらなる情報

さらなる情報については、当社の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でいくつかのタイムアウト設定を調整する必要があります。

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

  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");