メインコンテンツへスキップ
メインコンテンツへスキップ

Java クライアント

DBサーバーとそのプロトコルを通じて通信するためのJavaクライアントライブラリ。現在の実装ではHTTPインターフェースのみをサポートしています。 このライブラリは、サーバーへのリクエスト送信用の独自APIを提供します。また、異なるバイナリデータ形式(RowBinary* & Native*)を扱うためのツールも提供します。

セットアップ


<dependency>
    <groupId>com.clickhouse</groupId>
    <artifactId>client-v2</artifactId>
    <version>0.9.6</version>
</dependency>

初期化

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

ClientAutoCloseableを実装しており、不要になったら必ずクローズする必要があります。

認証

認証は初期化時にクライアントごとに設定します。サポートされている認証方式は3種類あり、パスワード認証、アクセストークン認証、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クライアント証明書による認証を行うには、setUsername(String)useSSLAuthentication(boolean)setClientCertificate(String)setClientKey(String) をそれぞれ呼び出して、ユーザー名の設定、SSL 認証の有効化、およびクライアント証明書とクライアントキーの設定を行う必要があります:

Client client = new Client.Builder()
        .useSSLAuthentication(true)
        .setUsername("some_user")
        .setClientCertificate("some_user.crt")
        .setClientKey("some_user.key")
注記

SSL認証は、SSLライブラリから出力されるエラーの多くが十分な情報を提供しないため、本番環境でのトラブルシューティングが困難になる場合があります。例えば、クライアント証明書と秘密鍵が一致しない場合、サーバーは即座に接続を切断します(HTTP の場合、HTTP リクエストが送信される前の接続確立段階で切断されるため、レスポンスは一切返されません)。

証明書と鍵を検証するには、opensslのようなツールを使用してください:

  • 秘密鍵の整合性を確認します: openssl rsa -in [key-file.key] -check -noout
  • クライアント証明書の CN が対象ユーザーのものと一致していることを確認する:
    • ユーザー証明書から CN を取得します - openssl x509 -noout -subject -in [user.cert]
    • 次のクエリを実行して、同じ値がデータベースに設定されていることを確認します: select name, auth_type, auth_params from system.users where auth_type = 'ssl_certificate'(このクエリでは、auth_params {"common_names":["some_user"]} のような値が出力されます)

設定

すべての設定はインスタンスメソッド(構成メソッドとも呼ばれる)によって定義され、各値のスコープとコンテキストが明確になります。 主要な設定パラメータは1つのスコープ(クライアントまたは操作)で定義され、互いに上書きされることはありません。

設定はクライアント作成時に定義します。com.clickhouse.client.api.Client.Builderを参照してください。

クライアント構成

MethodArgumentsDescriptionDefaultKey
addEndpoint(String endpoint)endpoint - URL 形式のサーバーアドレス利用可能なサーバーのリストにサーバーエンドポイントを追加します。現在は 1 つのエンドポイントのみがサポートされています。nonenone
addEndpoint(Protocol protocol, String host, int port, boolean secure)protocol - 接続プロトコル
host - IP もしくはホスト名
secure - HTTPS を使用するかどうか
利用可能なサーバーのリストにサーバーエンドポイントを追加します。現在は 1 つのエンドポイントのみがサポートされています。nonenone
enableConnectionPool(boolean enable)enable - 有効/無効を切り替えるフラグコネクションプールを有効にするかどうかを設定します。trueconnection_pool_enabled
setMaxConnections(int maxConnections)maxConnections - コネクション数各サーバーエンドポイントに対してクライアントが開くことができる接続数の上限を設定します。10max_open_connections
setConnectionTTL(long timeout, ChronoUnit unit)timeout - タイムアウト値
unit - 時間単位
接続が非アクティブと見なされるまでの有効期限 (TTL) を設定します。-1connection_ttl
setKeepAliveTimeout(long timeout, ChronoUnit unit)timeout - タイムアウト値
unit - 時間単位
HTTP 接続の Keep-Alive タイムアウトを設定します。Keep-Alive を無効にするには 0 を設定します。-http_keep_alive_timeout
setConnectionReuseStrategy(ConnectionReuseStrategy strategy)strategy - LIFO または FIFOコネクションプールが使用する接続再利用戦略を選択します。FIFOconnection_reuse_strategy
setDefaultDatabase(String database)database - データベース名デフォルトデータベースを設定します。defaultdatabase

サーバー設定

サーバー側の設定は、クライアント作成時に一度クライアントレベルで設定できます(BuilderserverSettingメソッドを参照)。また、操作レベルでも設定できます(操作設定クラスの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 がサポートしていない操作

このクライアントバージョンは以下をサポートします:

フォーマット入力出力
TabSeparatedrawraw
TabSeparatedRawrawraw
TabSeparatedWithNamesrawraw
TabSeparatedWithNamesAndTypesrawraw
TabSeparatedRawWithNamesrawraw
TabSeparatedRawWithNamesAndTypesrawraw
Templaterawraw
TemplateIgnoreSpacesraw*
CSVrawraw
CSVWithNamesrawraw
CSVWithNamesAndTypesrawraw
CustomSeparatedrawraw
CustomSeparatedWithNamesrawraw
CustomSeparatedWithNamesAndTypesrawraw
SQLInsert-raw
Valuesrawraw
Vertical*raw
JSONrawraw
JSONAsStringraw-
JSONAsObjectraw*
JSONStringsrawraw
JSONColumnsrawraw
JSONColumnsWithMetadatarawraw
JSONCompactrawraw
JSONCompactStrings-raw
JSONCompactColumnsrawraw
JSONEachRowrawraw
PrettyJSONEachRow*raw
JSONEachRowWithProgress-raw
JSONStringsEachRowrawraw
JSONStringsEachRowWithProgress*raw
JSONCompactEachRowrawraw
JSONCompactEachRowWithNamesrawraw
JSONCompactEachRowWithNamesAndTypesrawraw
JSONCompactStringsEachRowrawraw
JSONCompactStringsEachRowWithNamesrawraw
JSONCompactStringsEachRowWithNamesAndTypesrawraw
JSONObjectEachRowrawraw
BSONEachRowrawraw
TSKVrawraw
Pretty-raw
PrettyNoEscapes*raw
PrettyMonoBlock-raw
PrettyNoEscapesMonoBlock*raw
PrettyCompact-raw
PrettyCompactNoEscapes*raw
PrettyCompactMonoBlock-raw
PrettyCompactNoEscapesMonoBlock*raw
PrettySpace-raw
PrettySpaceNoEscapes*raw
PrettySpaceMonoBlock-raw
PrettySpaceNoEscapesMonoBlock*raw
Prometheus-raw
Protobufrawraw
ProtobufSinglerawraw
ProtobufListrawraw
Avrorawraw
AvroConfluentraw*
Parquetrawraw
ParquetMetadataraw-
Arrowrawraw
ArrowStreamrawraw
ORCrawraw
Oneraw*
Npyraw生データ
RowBinaryfullfull
RowBinaryWithNamesfullfull
RowBinaryWithNamesAndTypesフルフル
RowBinaryWithDefaultsfull-
Nativefull生データ
Null*raw
XML-raw
CapnProtoraw生データ
LineAsStringrawraw
Regexpraw*
RawBLOBrawraw
MsgPackrawraw
MySQLDumpraw-
DWARFraw*
Markdown-raw
Formraw*

Insert API

insert(String tableName, InputStream data, ClickHouseFormat format)

指定されたフォーマットのバイト列をInputStreamとして受け取ります。dataformatでエンコードされている必要があります。

署名

CompletableFuture<InsertResponse> insert(String tableName, InputStream data, ClickHouseFormat format, InsertSettings settings)
CompletableFuture<InsertResponse> insert(String tableName, InputStream data, ClickHouseFormat format)

パラメータ

tableName - 対象テーブル名。

data - エンコードされたデータの入力ストリーム。

format - データのエンコードに使用される形式。

settings - リクエスト設定。

戻り値

InsertResponse 型の Future — 操作の結果とサーバー側のメトリクスなどの追加情報。

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 - リクエスト設定。

戻り値

InsertResponse 型の Future - 操作結果とサーバー側メトリクスなどの追加情報。

// 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)操作に割り当てるクエリ ID を設定します。デフォルト: null
setDeduplicationToken(String token)重複排除トークンを設定します。このトークンはサーバーに送信され、クエリを識別するために利用できます。デフォルト: null
setInputStreamCopyBufferSize(int size)コピー用バッファのサイズ。書き込み操作時に、ユーザーが提供した入力ストリームから出力ストリームへデータをコピーする際に使用されます。デフォルト: 8196
serverSetting(String name, String value)個々の操作に対するサーバー設定を指定します。
serverSetting(String name, Collection values)操作用に複数の値を持つ個別のサーバー設定を指定します。コレクションの要素は String 型の値である必要があります。
setDBRoles(Collection dbRoles)操作の実行前に有効にする DB ロールを設定します。コレクションの要素はすべて String 値である必要があります。
setOption(String option, Object value)構成オプションを生の値として設定します。これはサーバー設定ではありません。

InsertResponse

挿入操作の結果を保持するレスポンスオブジェクト。クライアントがサーバーからレスポンスを受け取った場合にのみ利用可能です。

注記

このオブジェクトは接続を解放するため、できるだけ早くクローズする必要があります。前のレスポンスのすべてのデータが完全に読み取られるまで、接続を再利用できません。

メソッド説明
OperationMetrics getMetrics()操作メトリクスを表すオブジェクトを返します。
String getQueryId()アプリケーション(操作設定経由)またはサーバーによってこの操作に割り当てられたクエリ ID を返します。

クエリAPI

query(String sqlQuery)

sqlQueryをそのまま送信します。レスポンス形式はクエリ設定によって決まります。QueryResponseは、指定された形式に対応したリーダーが読み取るべきレスポンスストリームへの参照を保持します。

署名

CompletableFuture<QueryResponse> query(String sqlQuery, QuerySettings settings)
CompletableFuture<QueryResponse> query(String sqlQuery)

パラメータ

sqlQuery - 単一のSQLステートメントです。クエリはそのままサーバーに送信されます。

settings - リクエスト設定。

戻り値

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 - リクエスト設定。

戻り値

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形式でデータをクエリします。結果はコレクションとして返されます。読み取りパフォーマンスはリーダーと同じですが、データセット全体を保持するためにより多くのメモリが必要になります。

署名

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)操作に割り当てられるクエリ ID を設定します。
setFormat(ClickHouseFormat format)レスポンス形式を設定します。利用可能な形式の完全な一覧については RowBinaryWithNamesAndTypes を参照してください。
setMaxExecutionTime(Integer maxExecutionTime)サーバー側での操作の最大実行時間を設定します。読み取りタイムアウトには影響しません。
waitEndOfQuery(Boolean waitEndOfQuery)レスポンスを返す前にクエリの終了を待機するようサーバーに要求します。
setUseServerTimeZone(Boolean useServerTimeZone)クライアント設定で指定されたサーバーのタイムゾーンが、操作結果内の日付/時刻型を解釈する際に使用されます。デフォルトは false です。
setUseTimeZone(String timeZone)サーバーに対し、時刻変換に timeZone を使用するよう要求します。session_timezone を参照してください。
serverSetting(String name, String value)操作ごとに個別のサーバー設定を指定します。
serverSetting(String name, Collection values)操作用に複数の値を持つ個別のサーバー設定を指定します。コレクションの要素は String 型の値である必要があります。
setDBRoles(Collection dbRoles)操作実行前に有効化する DB ロールを設定します。コレクションの要素はすべて String 値である必要があります。
setOption(String option, Object value)構成オプションを生の形式で設定します。これはサーバー設定ではありません。

QueryResponse

クエリの実行結果を保持するレスポンスオブジェクトです。クライアントがサーバーからレスポンスを受け取った場合にのみ利用可能です。

注記

このオブジェクトは接続を解放するため、できるだけ早くクローズする必要があります。前のレスポンスのすべてのデータが完全に読み取られるまで、接続は再利用できません。

メソッド説明
ClickHouseFormat getFormat()レスポンスデータのエンコード形式を返します。
InputStream getInputStream()指定された形式の非圧縮データのバイトストリームを返します。
OperationMetrics getMetrics()操作メトリクスを表すオブジェクトを返します。
String getQueryId()アプリケーション(操作設定またはサーバー)によってこの操作に割り当てられたクエリ ID を返します。
TimeZone getTimeZone()レスポンス内の Date/DateTime 型を処理する際に使用するタイムゾーンを返します。

  • サンプルコードはリポジトリで公開されています
  • Spring サービスの実装を参照してください

共通 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 - スキーマを返す"SELECT" SQLステートメント。

戻り値

sql式に対応するカラムを含むTableSchemaオブジェクトを返します。

TableSchema

register(Class<?> clazz, TableSchema schema)

Java クラスが schema を使用してデータの書き込み/読み取りを行うためのシリアライゼーションおよびデシリアライゼーション層を生成します。このメソッドは、getter/setter のペアと対応するカラムに対してシリアライザーとデシリアライザーを作成します。 カラムの対応付けは、メソッド名からカラム名を抽出することで行われます。例えば、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)アプリケーションでクライアントを使用するサンプルです。

データの読み取り

データを読み込む一般的な方法は2つあります。

  • query() メソッドは、データを含む InputStream を保持する低レベルな QueryResponse オブジェクトを返します。通常はストリーミング読み取りのために 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
    }
}


## Migration Guide                   


Old client (V1) was using `com.clickhouse.client.ClickHouseClient#builder` as start point. The new client (V2) uses similar pattern with `com.clickhouse.client.api.Client.Builder`. Main
differences are:
- no service loader is used to grab implementation. The `com.clickhouse.client.api.Client` is facade class for all kinds of implementation in the future.
- a fewer sources of configuration: one is provided to the builder and one is with operation settings (`QuerySettings`, `InsertSettings`). Previous version had configuration per node and was loading
env. variables in some cases.

### Configuration Parameters Match                            

There are 3 enum classes related to configuration in V1:
- `com.clickhouse.client.config.ClickHouseDefaults` - configuration parameters that supposed to be set in most use cases. Like `USER` and `PASSWORD`.
- `com.clickhouse.client.config.ClickHouseClientOption` - configuration parameters specific for the client. Like `HEALTH_CHECK_INTERVAL`.
- `com.clickhouse.client.http.config.ClickHouseHttpOption` - configuration parameters specific for HTTP interface. Like `RECEIVE_QUERY_PROGRESS`.

They were designed to group parameters and provide clear separation. However in some cases it lead to a confusion (is there a difference between `com.clickhouse.client.config.ClickHouseDefaults#ASYNC` and
`com.clickhouse.client.config.ClickHouseClientOption#ASYNC`). The new V2 client uses `com.clickhouse.client.api.Client.Builder` as single dictionary of all possible client configuration options.There is
`com.clickhouse.client.api.ClientConfigProperties` where all configuration parameter names are listed.

Table below shows what old options are supported in the new client and their new meaning.

**Legend:** ✔ = supported, ✗ = dropped

<Tabs groupId="v1-migration">
<TabItem value="connection-auth" label="Connection & Auth">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseDefaults#HOST` | `Client.Builder#addEndpoint` | |
| `ClickHouseDefaults#PROTOCOL` | ✗ | Only HTTP supported in V2 |
| `ClickHouseDefaults#DATABASE`<br/>`ClickHouseClientOption#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_ALIVE`<br/>`ClickHouseHttpOption#KEEP_ALIVE_TIMEOUT` | `Client.Builder#setKeepAliveTimeout` | |
| `ClickHouseHttpOption#CONNECTION_REUSE_STRATEGY` | `Client.Builder#setConnectionReuseStrategy` | |
| `ClickHouseHttpOption#USE_BASIC_AUTHENTICATION` | `Client.Builder#useHTTPBasicAuth` | |

</TabItem>

<TabItem value="ssl" label="SSL & Security">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseDefaults#SSL_CERTIFICATE_TYPE` | ✗ | |
| `ClickHouseDefaults#SSL_KEY_ALGORITHM` | ✗ | |
| `ClickHouseDefaults#SSL_PROTOCOL` | ✗ | |
| `ClickHouseClientOption#SSL` | ✗ | See `Client.Builder#addEndpoint` |
| `ClickHouseClientOption#SSL_MODE` | ✗ | |
| `ClickHouseClientOption#SSL_ROOT_CERTIFICATE` | `Client.Builder#setRootCertificate` | SSL Auth should be enabled by `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` | ✗ | See `Client.Builder#sslSocketSNI` to set SNI |

</TabItem>

<TabItem value="socket" label="Socket Options">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `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` | |

</TabItem>

<TabItem value="compression" label="Compression">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseClientOption#COMPRESS` | `Client.Builder#compressServerResponse` | See also `useHttpCompression` |
| `ClickHouseClientOption#DECOMPRESS` | `Client.Builder#compressClientRequest` | See also `useHttpCompression` |
| `ClickHouseClientOption#COMPRESS_ALGORITHM` | ✗ | `LZ4` for non-http. Http uses `Accept-Encoding` |
| `ClickHouseClientOption#DECOMPRESS_ALGORITHM` | ✗ | `LZ4` for non-http. Http uses `Content-Encoding` |
| `ClickHouseClientOption#COMPRESS_LEVEL` | ✗ | |
| `ClickHouseClientOption#DECOMPRESS_LEVEL` | ✗ | |

</TabItem>

<TabItem value="proxy" label="Proxy">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `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` | |

</TabItem>

<TabItem value="timeouts-retry" label="Timeouts & Retry">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseClientOption#MAX_EXECUTION_TIME` | `Client.Builder#setExecutionTimeout` | |
| `ClickHouseClientOption#RETRY` | `Client.Builder#setMaxRetries` | See also `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` | ✗ | |

</TabItem>

<TabItem value="timezone" label="Timezone">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseDefaults#SERVER_TIME_ZONE`<br/>`ClickHouseClientOption#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` | |

</TabItem>

<TabItem value="buffers" label="Buffers & Performance">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `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` | ✗ | |

</TabItem>

<TabItem value="threading" label="Threading & Async">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseDefaults#ASYNC`<br/>`ClickHouseClientOption#ASYNC` | `Client.Builder#useAsyncRequests` | |
| `ClickHouseDefaults#MAX_SCHEDULER_THREADS` | ✗ | see `setSharedOperationExecutor` |
| `ClickHouseDefaults#MAX_THREADS` | ✗ | see `setSharedOperationExecutor` |
| `ClickHouseDefaults#THREAD_KEEPALIVE_TIMEOUT` | see `setSharedOperationExecutor` | |
| `ClickHouseClientOption#MAX_THREADS_PER_CLIENT` | ✗ | |
| `ClickHouseClientOption#MAX_CORE_THREAD_TTL` | ✗ | |

</TabItem>

<TabItem value="http-headers" label="HTTP & Headers">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseHttpOption#CUSTOM_HEADERS` | `Client.Builder#httpHeaders` | |
| `ClickHouseHttpOption#CUSTOM_PARAMS` | ✗ | See `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` | ✗ | Always enabled when Apache Http Client is used |

</TabItem>

<TabItem value="format-query" label="Format & Query">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseDefaults#FORMAT`<br/>`ClickHouseClientOption#FORMAT` | ✗ | Moved to operation settings (`QuerySettings` and `InsertSettings`) |
| `ClickHouseClientOption#QUERY_ID` | ✗ | See `QuerySettings` and `InsertSettings` |
| `ClickHouseClientOption#LOG_LEADING_COMMENT` | ✗ | See `QuerySettings#logComment` and `InsertSettings#logComment` |
| `ClickHouseClientOption#MAX_RESULT_ROWS` | ✗ | Is server side setting |
| `ClickHouseClientOption#RESULT_OVERFLOW_MODE` | ✗ | Is server side setting |
| `ClickHouseHttpOption#RECEIVE_QUERY_PROGRESS` | ✗ | Server side setting |
| `ClickHouseHttpOption#WAIT_END_OF_QUERY` | ✗ | Server side setting |
| `ClickHouseHttpOption#REMEMBER_LAST_SET_ROLES` | `Client#setDBRoles` | Runtime config now. See also `QuerySettings#setDBRoles` and `InsertSettings#setDBRoles` |

</TabItem>

<TabItem value="node-discovery" label="Node Discovery & Load Balancing">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `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` | ✗ | |

</TabItem>

<TabItem value="misc" label="Miscellaneous">

| V1 Configuration | V2 Builder Method | Comments |
|------------------|-------------------|----------|
| `ClickHouseDefaults#AUTO_SESSION` | ✗ | Session support will be reviewed |
| `ClickHouseDefaults#BUFFERING` | ✗ | |
| `ClickHouseDefaults#MAX_REQUESTS` | ✗ | |
| `ClickHouseDefaults#ROUNDING_MODE` | | |
| `ClickHouseDefaults#SERVER_VERSION`<br/>`ClickHouseClientOption#SERVER_VERSION` | `Client.Builder#setServerVersion` | |
| `ClickHouseDefaults#SRV_RESOLVE` | ✗ | |
| `ClickHouseClientOption#CUSTOM_SETTINGS` | | |
| `ClickHouseClientOption#PRODUCT_NAME` | ✗ | Use client 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` | ✗ | |

</TabItem>
</Tabs>


### General Differences

- Client V2 uses less proprietary classes to increase portability. For example, V2 works with any implementation of `java.io.InputStream` for
writing data to a server.
- Client V2 `async` settings is `off` by default. It means no extra threads and more application control over client. This setting should be `off` for majority of use cases. Enabling `async` will create a separate thread for a request. It only make sense when using application controlled
executor (see `com.clickhouse.client.api.Client.Builder#setSharedOperationExecutor`)

### Writing Data

- use any implementation of `java.io.InputStream`. V1 `com.clickhouse.data.ClickHouseInputStream` is supported but NOT recommended.
- once end of input stream is detected it handled accordingly. Previously output stream of a request should be closed.

__V1 Insert TSV formatted data.__
```java
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
}
  • 呼び出すメソッドは 1 つだけで、別途リクエストオブジェクトを作成する必要はありません。
  • リクエストボディストリームは、すべてのデータのコピーが完了すると自動的にクローズされます。
  • 新しい低レベル 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");
}

DBサーバーとそのプロトコルを通じて通信するためのJavaクライアントライブラリ。現在の実装ではHTTPインターフェースのみをサポートしています。このライブラリは、サーバーへのリクエスト送信用の独自APIを提供します。

非推奨

このライブラリは間もなく非推奨になります。新規プロジェクトには最新のJava クライアントを使用してください。

セットアップ

<!-- 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>

バージョン 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>

初期化

接続URL形式: protocol://host[:port][/database][?param[=value][&param[=value]][#tag[,tag]]、例:

単一ノードに接続する:

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();
            // type conversion
            String str = r.getValue(0).asString();
            LocalDate date = r.getValue(0).asDate();
        }
}

リポジトリ内の完全なコード例を参照してください。

Insert 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` is source of data in RowBinary format
        .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>

接続URLで compress_algorithm=gzip を設定すると、代わりに gzip を使用することができます。

あるいは、圧縮を無効にする方法もいくつかあります。

  1. 接続URLで compress=0 を指定して圧縮を無効化します: http://localhost:8123/default?compress=0
  2. クライアント設定で無効化します:
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()) {
            //...
        }
}
パラメータ

String型を含むすべてのparamsシグネチャ(StringString[]Map<String, String>)は、渡されるキーが有効なClickHouse SQL文字列であることを前提としています。例:

try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
     ClickHouseResponse response = client.read(servers)
        .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
        .query("select * from my_table where name=:name")
        .params(Map.of("name","'Ben'"))
        .executeAndWait()) {
            //...
        }
}

String オブジェクトを手動で ClickHouse SQL にパースしたくない場合は、com.clickhouse.data にあるヘルパー関数 ClickHouseValues.convertToSqlExpression を使用できます:

try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
     ClickHouseResponse response = client.read(servers)
        .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
        .query("select * from my_table where name=:name")
        .params(Map.of("name", ClickHouseValues.convertToSqlExpression("Ben's")))
        .executeAndWait()) {
            //...
        }
}

上記の例では、ClickHouseValues.convertToSqlExpressionが内部のシングルクォートをエスケープし、変数の両端を有効なシングルクォートで囲みます。

IntegerUUIDArrayEnum などのその他の型は、params 内で自動的に変換されます。

ノードディスカバリー

Javaクライアントには、ClickHouseノードを自動検出する機能があります。自動検出はデフォルトで無効になっています。手動で有効にするには、auto_discoverytrueに設定します:

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

または接続URLで指定します:

jdbc:ch://my-server/system?auto_discovery=true

自動検出が有効になっている場合、接続URLにすべてのClickHouseノードを指定する必要はありません。URLに指定されたノードはシードとして扱われ、Javaクライアントはシステムテーブルやclickhouse-keeper、zookeeperから追加のノードを自動的に検出します。

以下のオプションは自動検出の構成に使用します:

プロパティデフォルト説明
auto_discoveryfalseクライアントが system テーブルおよび/または clickhouse-keeper/zookeeper から追加のノードを検出するかどうか。
node_discovery_interval0ノード検出の実行間隔(ミリ秒)。値が 0 または負の場合は、一度だけ検出を実行することを意味します。
node_discovery_limit100一度に検出対象となるノードの最大数。0 以下の値は上限なしを意味します。

ロードバランシング

Javaクライアントは負荷分散ポリシーに従ってリクエストを送信するClickHouseノードを選択します。一般的に、負荷分散ポリシーは次の事項を担当します:

  1. 管理対象ノードリストからノードを1つ取得します。
  2. ノードの状態を管理する。
  3. 必要に応じて(自動ディスカバリが有効な場合)、ノードディスカバリ用のバックグラウンドプロセスをスケジュールし、ヘルスチェックを実行します。

ロードバランシングを構成するためのオプションは次のとおりです:

プロパティデフォルト説明
load_balancing_policy""ロードバランシングポリシーは次のいずれかです:
  • firstAlive - リクエストは管理対象ノードリストの最初の正常なノードに送信されます
  • random - リクエストは管理対象ノードリストからランダムに選択されたノードに送信されます
  • roundRobin - リクエストは管理対象ノードリスト内の各ノードに順番に送信されます
  • ClickHouseLoadBalancingPolicy を実装する完全修飾クラス名 - カスタムロードバランシングポリシー
  • ポリシーが指定されていない場合、リクエストは管理対象ノードリストの最初のノードに送信されます
    load_balancing_tags""ノードを絞り込むためのロードバランシング用タグ。リクエストは指定したタグを持つノードにのみ送信されます。
    health_check_interval0ヘルスチェックの間隔をミリ秒単位で指定します。0 以下の値は一度だけ実行されることを意味します。
    health_check_methodClickHouseHealthCheckMethod.SELECT_ONEヘルスチェックの方法。次のいずれかを指定できます:
  • ClickHouseHealthCheckMethod.SELECT_ONE - select 1 クエリの実行によってチェックします
  • ClickHouseHealthCheckMethod.PING - プロトコル固有のチェックで、一般的により高速です
  • node_check_interval0ノードチェック間隔(ミリ秒単位)。負の値は 0 として扱われます。前回のチェックから指定した時間が経過している場合にノードのステータスがチェックされます。
    health_check_intervalnode_check_interval の違いは、health_check_interval オプションがノード(全ノードまたは障害ノード)のリストに対してステータスをチェックするバックグラウンドジョブをスケジューリングするのに対し、node_check_interval は特定のノードについて、前回のチェックからどれだけの時間が経過した後にチェックを行うかを指定する点です
    check_all_nodesfalseすべてのノードを対象にヘルスチェックを行うか、障害が発生しているノードのみを対象にするかを指定します。

    フェイルオーバーとリトライ

    Javaクライアントは、失敗したクエリのフェイルオーバーおよびリトライ動作を設定するための構成オプションを提供します:

    プロパティデフォルト説明
    failover01 つのリクエストに対して許可されるフェイルオーバーの最大回数。0 または負の値の場合は、フェイルオーバーは行われません。フェイルオーバーでは、障害から復旧するために、失敗したリクエストを(負荷分散ポリシーに従って)別のノードに送信します。
    retry01 つのリクエストに対して許可されるリトライの最大回数。0 または負の値の場合はリトライを行いません。リトライは、ClickHouse サーバーが NETWORK_ERROR エラーコードを返した場合にのみ、同じノードに対してリクエストを再送信します
    repeat_on_session_locktrueセッションがロックされている場合に、session_timeout または connect_timeout に従ってタイムアウトに達するまで実行を繰り返すかどうか。ClickHouse サーバーが SESSION_IS_LOCKED エラーコードを返した場合には、その失敗したリクエストを再試行します

    カスタムHTTPヘッダーの追加

    Javaクライアントは、リクエストにカスタムHTTPヘッダーを追加したい場合、HTTP/Sトランスポート層をサポートしています。 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");