ClickHouse に接続するための公式 JS client です。
この client は TypeScript で書かれており、client の公開 API 向けの型定義を提供します。
dependencies は一切なく、最大限のパフォーマンスを発揮できるよう最適化されており、さまざまな ClickHouse のバージョンと構成 (オンプレミスのシングルノード、オンプレミスのクラスター、ClickHouse Cloud) でテストされています。
環境ごとに、2 種類の client が用意されています。
@clickhouse/client - Node.js のみ
@clickhouse/client-web - ブラウザー (Chrome/Firefox) 、Cloudflare workers
TypeScript を使用する場合は、インライン import/export 構文が利用できる バージョン 4.5 以上を使用してください。
client のソースコードは、ClickHouse-JS GitHub repository で公開されています。
AI agent スキルJS client には、コーディング agents が client を利用する際に役立つ AI agent スキルが付属しています。次のコマンドでインストールしてください。npm skills add ClickHouse/clickhouse-js
クライアントを実行するには、環境で Node.js を利用できる必要があります。
このクライアントは、メンテナンス対象のすべての Node.js リリースと互換性があります。
Node.js のバージョンがサポート終了に近づくと、そのバージョンは古く安全ではないと見なされるため、クライアントはそのサポートを終了します。
現在サポートされている Node.js のバージョン:
| Node.js version | Supported? |
|---|
| 24.x | ✔ |
| 22.x | ✔ |
| 20.x | ✔ |
| 18.x | ベストエフォート |
クライアントのWeb 版は、最新の Chrome/Firefox ブラウザーで正式にテストされており、たとえば React/Vue/Angular アプリケーションや Cloudflare Workers の依存関係として利用できます。
最新の安定版 Node.js クライアントをインストールするには、次を実行します:
Web 版のインストール:
npm i @clickhouse/client-web
| クライアントのバージョン | ClickHouse |
|---|
| 1.12.0 | 24.8+ |
古いバージョンのクライアントでも動作する可能性はありますが、これはベストエフォートでのサポートであり、動作は保証されません。23.3 より前の ClickHouse バージョンを使用している場合は、ClickHouse security policy を参照し、アップグレードを検討してください。
クライアントの利用方法に関するさまざまなシナリオを、クライアント リポジトリ内のexamplesで紹介しています。
概要はexamples READMEで確認できます。
examples や以下のドキュメントについて不明な点や不足している内容があれば、お問い合わせください。
特に明記がない限り、ほとんどの例はクライアントの Node.js 版と Web 版の両方で使用できます。
createClient ファクトリーを使用すると、必要な数のクライアントインスタンスを作成できます。
import { createClient } from '@clickhouse/client' // または '@clickhouse/client-web'
const client = createClient({
/* 設定 */
})
お使いの環境でESMモジュールがサポートされていない場合は、代わりにCJS構文を使用できます。
const { createClient } = require('@clickhouse/client');
const client = createClient({
/* 設定 */
})
クライアントのインスタンスは、インスタンス化時にあらかじめ設定できます。
クライアントインスタンスの作成時に、次の接続設定を調整できます。
| 設定 | 説明 | デフォルト値 | 関連項目 | |
|---|
| url?: string | ClickHouse インスタンスの URL。 | http://localhost:8123 | URL 設定のドキュメント | |
| pathname?: string | クライアントによる解析後に ClickHouse URL に追加する、省略可能なパス名。 | '' | パス名付きプロキシのドキュメント | |
| request_timeout?: number | リクエストのタイムアウト時間 (ミリ秒) 。 | 30_000 | - | |
compression?: { **response**?: boolean; **request**?: boolean } | 圧縮を有効にします。 | - | 圧縮のドキュメント | |
| username?: string | リクエストの送信元として使用するユーザー名。 | default | - | |
| password?: string | ユーザーのパスワード。 | '' | - | |
| application?: string | Node.js クライアント を使用するアプリケーション名。 | clickhouse-js | - | |
| database?: string | 使用するデータベース名。 | default | - | |
| clickhouse_settings?: ClickHouseSettings | すべてのリクエストに適用する ClickHouse settings。 | {} | - | |
log?: { **LoggerClass**?: Logger, **level**?: ClickHouseLogLevel } | クライアント内部のログ設定。 | - | ログのドキュメント | |
| session_id?: string | すべてのリクエストに送信する、省略可能な ClickHouse Session ID。 | - | - | |
keep_alive?: { **enabled**?: boolean } | Node.js 版と Web 版の両方で、デフォルトで有効です。 | - | - | |
http_headers?: Record<string, string> | 送信する ClickHouse リクエストに追加する HTTP ヘッダー。 | - | authentication 付きリバースプロキシのドキュメント | |
| roles?: string | string[] | 送信するリクエストに付与する ClickHouse ロール名。 | - | HTTP インターフェイスでのロールの使用 |
| 設定 | 説明 | デフォルト値 | 関連項目 | |
|---|
| max_open_connections?: number | ホストごとに許可されるソケット接続の最大数。 | 10 | - | |
tls?: { **ca_cert**: Buffer, **cert**?: Buffer, **key**?: Buffer } | TLS 証明書を設定します。 | - | TLS ドキュメント | |
keep_alive?: { **enabled**?: boolean, **idle_socket_ttl**?: number } | - | - | Keep Alive ドキュメント | |
| http_agent?: http.Agent | https.Agent
| クライアント用のカスタム HTTP Agent。 | - | HTTP agent ドキュメント |
set_basic_auth_header?: boolean
| basic 認証の認証情報を含む Authorization ヘッダーを設定します。 | true | HTTP agent ドキュメントでのこの設定の使用方法 | |
URL 設定はハードコードされた値を常に上書きし、この場合は警告がログに記録されます。
URL を使って、クライアントインスタンスのパラメータの大半を設定できます。URL の形式は http[s]://[username:password@]hostname:port[/database][?param1=value1¶m2=value2] です。ほとんどの場合、個々のパラメータ名は config options interface 内でのパスを反映していますが、いくつか例外があります。次のパラメータがサポートされています。
| パラメータ | 型 |
|---|
pathname | 任意の文字列。 |
application_id | 任意の文字列。 |
session_id | 任意の文字列。 |
request_timeout | 0 以上の数値。 |
max_open_connections | 0 より大きい数値。 |
compression_request | 真偽値。以下の (1) を参照。 |
compression_response | 真偽値。 |
log_level | 使用可能な値: OFF, TRACE, DEBUG, INFO, WARN, ERROR。 |
keep_alive_enabled | 真偽値。 |
clickhouse_setting_* or ch_* | 以下の (2) を参照。 |
http_header_* | 以下の (3) を参照。 |
(Node.js のみ) keep_alive_idle_socket_ttl | 0 以上の数値。 |
- (1) 真偽値では、有効な値は
true/1 と false/0 です。
- (2)
clickhouse_setting_ または ch_ で始まるパラメータは、このプレフィックスが削除され、残りがクライアントの clickhouse_settings に追加されます。たとえば、?ch_async_insert=1&ch_wait_for_async_insert=1 は次と同じです。
createClient({
clickhouse_settings: {
async_insert: 1,
wait_for_async_insert: 1,
},
})
注: clickhouse_settings の真偽値は、URL では 1/0 として渡す必要があります。
- (3)
http_header 設定についても (2) と同様です。たとえば、?http_header_x-clickhouse-auth=foobar は次と同等です。
createClient({
http_headers: {
'x-clickhouse-auth': 'foobar',
},
})
HTTP(S) で ClickHouse に接続するには、次の情報が必要です。
| Parameter(s) | Description |
|---|
HOST and PORT | 通常、TLS を使用する場合のポートは 8443、TLS を使用しない場合は 8123 です。 |
DATABASE NAME | デフォルトでは default という名前のデータベースがあります。接続先のデータベース名を使用してください。 |
USERNAME and PASSWORD | デフォルトのユーザー名は default です。用途に応じたユーザー名を使用してください。 |
ClickHouse Cloud サービスの詳細は、ClickHouse Cloud コンソールで確認できます。
サービスを選択し、Connect をクリックします。
HTTPS を選択します。接続情報は curl コマンドの例として表示されます。
セルフマネージド ClickHouse を使用している場合、接続情報は ClickHouse 管理者によって設定されます。
このクライアントは、HTTP または HTTPS プロトコルによる接続をサポートしています。RowBinary のサポートも進行中です。詳しくは関連 issueを参照してください。
以下の例では、ClickHouse Cloud への接続を設定する方法を示します。url (プロトコルとポートを含む) および password の値は環境変数で指定し、default ユーザーを使用することを前提としています。
例: 設定に環境変数を使用して Node.js クライアントインスタンスを作成します。
import { createClient } from '@clickhouse/client'
const client = createClient({
url: process.env.CLICKHOUSE_HOST ?? 'http://localhost:8123',
username: process.env.CLICKHOUSE_USER ?? 'default',
password: process.env.CLICKHOUSE_PASSWORD ?? '',
})
クライアントリポジトリには、環境変数を使用するサンプルが複数含まれており、たとえば ClickHouse Cloud でテーブルを作成する や 非同期 INSERT を使用する など、そのほかにも多数あります。
リクエストごとに接続を確立するオーバーヘッドを避けるため、クライアントは Keep-Alive の仕組みを利用して、再利用可能な ClickHouse への接続プールを作成します。デフォルトでは Keep-Alive は有効で、接続プールのサイズは 10 に設定されていますが、設定オプション max_open_connections で変更できます。
ユーザーが max_open_connections: 1 を設定しない限り、後続のクエリでプール内の同じ接続が使用される保証はありません。これは必要になることはほとんどありませんが、一時テーブルを使用する場合には必要になることがあります。
関連項目: Keep-Alive 設定。
クエリまたはステートメントを送信するすべてのメソッド (command、exec、insert、select) では、結果に query_id が含まれます。この一意の識別子はクライアントによってクエリごとに割り当てられ、サーバー設定 で有効になっていれば system.query_log からデータを取得したり、長時間実行されているクエリをキャンセルしたりする際に役立つことがあります (例 を参照) 。必要に応じて、query_id は command/query/exec/insert メソッドのパラメーターでユーザーが上書きできます。
query_id パラメーターを上書きする場合は、呼び出しごとに一意であることを保証する必要があります。ランダムな UUID を使うのが適切です。
Base parameters for all client methods
すべてのクライアントメソッド (query/command/insert/exec) に共通して適用できるパラメーターがいくつかあります。
interface BaseQueryParams {
// クエリレベルで適用できる ClickHouse settings。
clickhouse_settings?: ClickHouseSettings
// クエリバインディング用のパラメータ。
query_params?: Record<string, unknown>
// 実行中のクエリをキャンセルするための AbortSignal インスタンス。
abort_signal?: AbortSignal
// query_id のオーバーライド。指定しない場合、ランダムな識別子が自動的に生成されます。
query_id?: string
// session_id のオーバーライド。指定しない場合、セッション ID はクライアントの設定から取得されます。
session_id?: string
// credentials のオーバーライド。指定しない場合、クライアントの credentials が使用されます。
auth?: { username: string, password: string }
// このクエリで使用するロールのリスト。クライアント設定で指定されたロールを上書きします。
role?: string | Array<string>
}
このメソッドは、SELECT のように応答を返すほとんどのステートメントや、CREATE TABLE のような DDL の送信に使用し、await する必要があります。返された結果セットは、アプリケーション側で処理することが想定されています。
interface QueryParams extends BaseQueryParams {
// 実行するクエリ。データを返す場合があります。
query: string
// 結果データセットのフォーマット。デフォルト: JSON。
format?: DataFormat
}
interface ClickHouseClient {
query(params: QueryParams): Promise<ResultSet>
}
関連項目: Base parameters for all client methods。
query では FORMAT 句を指定せず、代わりに format パラメーターを使用してください。
ResultSet には、アプリケーションでのデータ処理に便利ないくつかのメソッドが用意されています。
Node.js の ResultSet 実装は内部で Stream.Readable を使用し、Web 版は Web API の ReadableStream を使用します。
ResultSet は、ResultSet の text または json メソッドを呼び出して消費でき、クエリが返した行セット全体をメモリに読み込めます。
ResultSet はレスポンスストリームを開いたまま保持し、その結果として基盤となる接続を占有し続けるため、できるだけ早く消費を開始してください。クライアントは、アプリケーションで過剰なメモリ使用量が発生するのを避けるため、受信データをバッファリングしません。
また、一度にメモリに収まらないほど大きい場合は、stream メソッドを呼び出してストリーミングモードでデータを処理できます。この場合、各レスポンス chunk は比較的小さな行の配列に変換されて処理されます (この配列のサイズは、クライアントがサーバーから受信する chunk のサイズ (可変) と、個々の行のサイズによって決まります) 。これを 1 chunk ずつ処理します。
ご利用のケースでストリーミングに最適なフォーマットを判断するには、サポートされているデータフォーマット の一覧を参照してください。たとえば、JSON オブジェクトをストリーミングしたい場合は JSONEachRow を選択でき、その場合は各行が JS オブジェクトとして解析されます。あるいは、よりコンパクトな JSONCompactColumns フォーマットを選ぶこともでき、この場合は各行が値のコンパクトな配列になります。関連項目: ファイルのストリーミング。
ResultSet またはそのストリームが最後まで消費されない場合、非アクティブ状態が request_timeout の期間続くと破棄されます。
interface BaseResultSet<Stream> {
// 上記の「Query ID」セクションを参照
query_id: string
// ストリーム全体を消費し、内容を文字列として取得する
// 任意の DataFormat で使用可能
// 一度だけ呼び出すこと
text(): Promise<string>
// ストリーム全体を消費し、内容を JS オブジェクトとしてパースする
// JSON フォーマットのみで使用可能
// 一度だけ呼び出すこと
json<T>(): Promise<T>
// ストリーミング可能なレスポンス用の読み取り可能なストリームを返す
// ストリームの各イテレーションは、選択した DataFormat の Row[] 配列を提供する
// 一度だけ呼び出すこと
stream(): Stream
}
interface Row {
// 行の内容をプレーン文字列として取得する
text: string
// 行の内容を JS オブジェクトとしてパースする
json<T>(): T
}
例: (Node.js/Web) JSONEachRow フォーマットの結果データセットを返すクエリ。ストリーム全体を消費し、内容を JS オブジェクトとしてパースします。
ソースコード.
const resultSet = await client.query({
query: 'SELECT * FROM my_table',
format: 'JSONEachRow',
})
const dataset = await resultSet.json() // または `row.text` でJSONのパースを回避
例: (Node.js のみ) 従来の on('data') アプローチを使って、JSONEachRow フォーマットでクエリ結果をストリーミングする例です。これは for await const 構文でも同様に実現できます。ソースコード。
const rows = await client.query({
query: 'SELECT number FROM system.numbers_mt LIMIT 5',
format: 'JSONEachRow', // または JSONCompactEachRow、JSONStringsEachRow など
})
const stream = rows.stream()
stream.on('data', (rows: Row[]) => {
rows.forEach((row: Row) => {
console.log(row.json()) // JSON のパースを避ける場合は `row.text` を使用
})
})
await new Promise((resolve, reject) => {
stream.on('end', () => {
console.log('Completed!')
resolve(0)
})
stream.on('error', reject)
})
例: (Node.js のみ) 従来の on('data') アプローチを使って、クエリ結果を CSV フォーマットでストリーミングします。これは for await const 構文でも同様に実装できます。
ソースコード
const resultSet = await client.query({
query: 'SELECT number FROM system.numbers_mt LIMIT 5',
format: 'CSV', // または TabSeparated、CustomSeparated など
})
const stream = resultSet.stream()
stream.on('data', (rows: Row[]) => {
rows.forEach((row: Row) => {
console.log(row.text)
})
})
await new Promise((resolve, reject) => {
stream.on('end', () => {
console.log('Completed!')
resolve(0)
})
stream.on('error', reject)
})
例: (Node.js のみ) for await const 構文を使用して、JSONEachRow フォーマットのクエリ結果を JS オブジェクトとしてストリーミングで処理する例です。これは従来の on('data') アプローチと同様に使用できます。
ソースコード.
const resultSet = await client.query({
query: 'SELECT number FROM system.numbers LIMIT 10',
format: 'JSONEachRow', // または JSONCompactEachRow、JSONStringsEachRow など
})
for await (const rows of resultSet.stream()) {
rows.forEach(row => {
console.log(row.json())
})
}
for await const 構文は on('data') を使う方法よりコード量をやや減らせますが、パフォーマンスに悪影響を与える可能性があります。
詳細については、Node.js リポジトリのこの issueを参照してください。
例: (Web のみ) オブジェクトの ReadableStream をイテレーション処理する例。
const resultSet = await client.query({
query: 'SELECT * FROM system.numbers LIMIT 10',
format: 'JSONEachRow'
})
const reader = resultSet.stream().getReader()
while (true) {
const { done, value: rows } = await reader.read()
if (done) { break }
rows.forEach(row => {
console.log(row.json())
})
}
これはデータを挿入するための主要なメソッドです。
export interface InsertResult {
query_id: string
executed: boolean
}
interface ClickHouseClient {
insert(params: InsertParams): Promise<InsertResult>
}
戻り値の型は最小限に抑えられています。これは、server からデータが返されることを想定しておらず、レスポンスストリームを直ちにドレインするためです。
空の配列が insert メソッドに渡された場合、insert ステートメントは server に送信されません。代わりに、このメソッドは直ちに { query_id: '...', executed: false } を返して解決されます。この場合、query_id がメソッドの params で指定されていなければ、結果では空文字列になります。存在しない query_id を返すと混乱を招くおそれがあるためです。クライアントがランダムに生成した UUID を返しても、その query_id を持つクエリは system.query_log table には存在しません。
insert ステートメントが server に送信された場合、executed フラグは true になります。
Node.js における Insertメソッド とストリーミング
これは、insert method に指定したデータフォーマットに応じて、Stream.Readable または通常の Array<T> のいずれでも利用できます。ファイルストリーミングについては、こちらのセクションも参照してください。
Insertメソッドは await して使用することが想定されています。ただし、入力ストリームを指定しておき、ストリームの完了後に insert 操作を await することも可能です (その時点で insert promise も解決されます) 。これはイベントリスナーなどの用途では有用な場合がありますが、クライアント側では考慮すべきエッジケースが多く、エラーハンドリングが複雑になりがちです。代わりに、この例で示されているように、非同期 INSERTの利用を検討してください。
interface InsertParams<T> extends BaseQueryParams {
// データを挿入するテーブル名
table: string
// 挿入するデータセット。
values: ReadonlyArray<T> | Stream.Readable
// 挿入するデータセットのフォーマット。
format?: DataFormat
// データを挿入するカラムを指定できます。
// - `['a', 'b']` のような配列を指定すると、`INSERT INTO table (a, b) FORMAT DataFormat` が生成されます。
// - `{ except: ['a', 'b'] }` のようなオブジェクトを指定すると、`INSERT INTO table (* EXCEPT (a, b)) FORMAT DataFormat` が生成されます。
// デフォルトでは、テーブルの全カラムにデータが挿入され、
// 生成されるステートメントは `INSERT INTO table FORMAT DataFormat` となります。
columns?: NonEmptyArray<string> | { except: NonEmptyArray<string> }
}
関連項目: Base parameters for all client methods。
abort_signal でリクエストをキャンセルしても、データが挿入されていないことは保証されません。キャンセル前に、サーバーがストリーミングされたデータの一部を受信している可能性があるためです。
例: (Node.js/Web) 値の配列を挿入します。
ソースコード。
await client.insert({
table: 'my_table',
// 構造は目的のフォーマットと一致する必要があります(この例では JSONEachRow)
values: [
{ id: 42, name: 'foo' },
{ id: 42, name: 'bar' },
],
format: 'JSONEachRow',
})
例: (Node.js のみ) CSVファイルのストリームを挿入します。
ソースコード。関連項目: ファイルのストリーミング。
await client.insert({
table: 'my_table',
values: fs.createReadStream('./path/to/a/file.csv'),
format: 'CSV',
})
例: insertステートメントから特定のカラムを除外します。
たとえば、次のようなテーブル定義があるとします:
CREATE OR REPLACE TABLE mytable
(id UInt32, message String)
ENGINE MergeTree()
ORDER BY (id)
特定のカラムのみに挿入します:
// 生成されるステートメント: INSERT INTO mytable (message) FORMAT JSONEachRow
await client.insert({
table: 'mytable',
values: [{ message: 'foo' }],
format: 'JSONEachRow',
// この行の `id` カラムの値はゼロになります(UInt32 のデフォルト値)
columns: ['message'],
})
特定のカラムを除外する:
// 生成されたステートメント: INSERT INTO mytable (* EXCEPT (message)) FORMAT JSONEachRow
await client.insert({
table: tableName,
values: [{ id: 144 }],
format: 'JSONEachRow',
// この行の `message` カラムの値は空文字列になります
columns: {
except: ['message'],
},
})
詳細は、ソースコードを参照してください。
例: クライアントインスタンスに指定したデータベースとは別のデータベースに挿入します。ソースコード。
await client.insert({
table: 'mydb.mytable', // データベース名を含む完全修飾名
values: [{ id: 42, message: 'foo' }],
format: 'JSONEachRow',
})
現在、@clickhouse/client-web での insert は、Array<T> および JSON* フォーマットでのみ利用できます。
ブラウザの互換性の問題により、Web 版ではストリームの insert はまだサポートされていません。
そのため、Web 版の InsertParams インターフェイスは Node.js 版とは少し異なり、
values は ReadonlyArray<T> 型にのみ制限されています:
interface InsertParams<T> extends BaseQueryParams {
// データを挿入するテーブル名
table: string
// 挿入するデータセット。
values: ReadonlyArray<T>
// 挿入するデータセットのフォーマット。
format?: DataFormat
// データを挿入するカラムを指定できます。
// - `['a', 'b']` のような配列を指定すると、`INSERT INTO table (a, b) FORMAT DataFormat` が生成されます。
// - `{ except: ['a', 'b'] }` のようなオブジェクトを指定すると、`INSERT INTO table (* EXCEPT (a, b)) FORMAT DataFormat` が生成されます。
// デフォルトでは、テーブルの全カラムにデータが挿入され、
// 生成されるステートメントは `INSERT INTO table FORMAT DataFormat` となります。
columns?: NonEmptyArray<string> | { except: NonEmptyArray<string> }
}
この内容は今後変更される可能性があります。関連項目: Base parameters for all client methods.
出力を返さないステートメントや、FORMAT 句を適用できない場合、あるいはレスポンスがまったく不要な場合に使用できます。そのようなステートメントの例としては、CREATE TABLE や ALTER TABLE があります。
await する必要があります。
レスポンスストリームは即座に破棄されるため、基盤となるソケットも解放されます。
interface CommandParams extends BaseQueryParams {
// 実行するステートメント。
query: string
}
interface CommandResult {
query_id: string
}
interface ClickHouseClient {
command(params: CommandParams): Promise<CommandResult>
}
関連項目: Base parameters for all client methods。
例: (Node.js/Web) ClickHouse Cloudでテーブルを作成します。
ソースコード。
await client.command({
query: `
CREATE TABLE IF NOT EXISTS my_cloud_table
(id UInt64, name String)
ORDER BY (id)
`,
// クラスター使用時に推奨される設定です。レスポンスコードの送信後にクエリ処理エラーが発生し、HTTP ヘッダーがすでにクライアントに送信されてしまう状況を防ぎます。
// See https://clickhouse.com/docs/interfaces/http/#response-buffering
clickhouse_settings: {
wait_end_of_query: 1,
},
})
例: (Node.js/Web) セルフホスト環境の ClickHouse インスタンスにテーブルを作成します。
ソースコード.
await client.command({
query: `
CREATE TABLE IF NOT EXISTS my_table
(id UInt64, name String)
ENGINE MergeTree()
ORDER BY (id)
`,
})
例: (Node.js/Web) INSERT FROM SELECT
await client.command({
query: `INSERT INTO my_table SELECT '42'`,
})
abort_signal でキャンセルされたリクエストでも、そのステートメントがサーバーで実行されなかったことは保証されません。
query/insert では扱えないカスタムなクエリがあり、
その結果を取得したい場合は、command の代わりに exec を使用できます。
exec は読み取り可能なストリームを返します。これは、アプリケーション側で必ず消費するか破棄する必要があります。
interface ExecParams extends BaseQueryParams {
// 実行するステートメント。
query: string
}
interface ClickHouseClient {
exec(params: ExecParams): Promise<QueryResult>
}
関連項目: Base parameters for all client methods。
ストリームの戻り値の型は、Node.js と Web 版で異なります。
Node.js:
export interface QueryResult {
stream: Stream.Readable
query_id: string
}
Web:
export interface QueryResult {
stream: ReadableStream
query_id: string
}
接続状態を確認するために提供されている ping メソッドは、サーバーに到達できる場合に true を返します。
サーバーに到達できない場合は、原因となるエラーも結果に含まれます。
type PingResult =
| { success: true }
| { success: false; error: Error }
/** ヘルスチェックリクエストのパラメータ - 組み込みの `/ping` エンドポイントを使用。
* これは Node.js 版のデフォルト動作です。 */
export type PingParamsWithEndpoint = {
select: false
/** 進行中のリクエストをキャンセルするための AbortSignal インスタンス。 */
abort_signal?: AbortSignal
/** このリクエストに付加する追加の HTTP ヘッダー。 */
http_headers?: Record<string, string>
}
/** ヘルスチェックリクエストのパラメータ - SELECT クエリを使用。
* `/ping` エンドポイントが CORS をサポートしていないため、これは Web 版のデフォルト動作です。
* 標準的な `query` メソッドのパラメータ(例: `query_id`、`abort_signal`、`http_headers` など)はほぼ利用可能ですが、
* `query_params` はこのメソッドでの使用が適切でないため除外されています。 */
export type PingParamsWithSelectQuery = { select: true } & Omit<
BaseQueryParams,
'query_params'
>
export type PingParams = PingParamsWithEndpoint | PingParamsWithSelectQuery
interface ClickHouseClient {
ping(params?: PingParams): Promise<PingResult>
}
アプリケーションの起動時にサーバーが利用可能かどうかを確認するには、Ping が役立つことがあります。特に ClickHouse Cloud では、インスタンスがアイドル状態になっていて、ping を受けると起動する場合があります。そのような場合は、間に遅延を挟んで数回再試行するとよいでしょう。
デフォルトでは、Node.js 版は /ping エンドポイントを使用します。一方、Web 版は /ping エンドポイントが CORS をサポートしていないため、同様の結果を得るために単純な SELECT 1 クエリを使用します。
例: (Node.js/Web) ClickHouse サーバーインスタンスへのシンプルな ping。注: Web 版では、発生するエラーは異なります。
ソースコード。
const result = await client.ping();
if (!result.success) {
// result.errorを処理する
}
例: ping メソッドの呼び出し時に認証情報も確認したり、query_id などの追加パラメータを指定したりする場合は、次のように使用できます。
const result = await client.ping({ select: true, /* query_id, abort_signal, http_headers、またはその他のクエリパラメータ */ });
pingメソッドでは、標準的な query メソッドのパラメーターの大半を利用できます。PingParamsWithSelectQuery の型定義を参照してください。
開いているすべての接続を閉じて、リソースを解放します。Web 版では何も行いません。
ファイルのストリーミング (Node.js のみ)
一般的なデータフォーマット (NDJSON、CSV、Parquet) を使用したファイルストリーミングの例が、クライアントリポジトリにいくつかあります。
他のフォーマットをファイルにストリーミングする場合も、Parquet とほぼ同様です。
異なるのは、query 呼び出しで使用するフォーマット (JSONEachRow、CSV など) と出力ファイル名だけです。
クライアントは、データフォーマットを JSON またはテキストとして処理します。
format に JSON 系のフォーマット (JSONEachRow、JSONCompactEachRow など) を指定すると、クライアントは通信時にデータをシリアライズおよびデシリアライズします。
「raw」テキストフォーマット (CSV、TabSeparated、CustomSeparated 系) で指定したデータは、追加の変換なしでそのまま送信されます。
| フォーマット | 入力 (配列) | 入力 (オブジェクト) | 入出力 (ストリーム) | 出力 (JSON) | 出力 (テキスト) |
|---|
| JSON | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONCompact | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONObjectEachRow | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONColumnsWithMetadata | ❌ | ✔️ | ❌ | ✔️ | ✔️ |
| JSONStrings | ❌ | ❌️ | ❌ | ✔️ | ✔️ |
| JSONCompactStrings | ❌ | ❌ | ❌ | ✔️ | ✔️ |
| JSONEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONEachRowWithProgress | ❌️ | ❌ | ✔️ ❗- 以下を参照 | ✔️ | ✔️ |
| JSONStringsEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactStringsEachRow | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactEachRowWithNames | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactEachRowWithNamesAndTypes | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactStringsEachRowWithNames | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| JSONCompactStringsEachRowWithNamesAndTypes | ✔️ | ❌ | ✔️ | ✔️ | ✔️ |
| CSV | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CSVWithNames | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CSVWithNamesAndTypes | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparated | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparatedRaw | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparatedWithNames | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| TabSeparatedWithNamesAndTypes | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CustomSeparated | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CustomSeparatedWithNames | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| CustomSeparatedWithNamesAndTypes | ❌ | ❌ | ✔️ | ❌ | ✔️ |
| Parquet | ❌ | ❌ | ✔️ | ❌ | ✔️❗- 以下を参照 |
Parquet では、select の主な用途は、結果のストリームをファイルに書き出すことになるでしょう。クライアントリポジトリのこの例を参照してください。
JSONEachRowWithProgress は、ストリーム内での進捗レポートをサポートする出力専用のフォーマットです。詳しくは、この例を参照してください。
ClickHouse の入力フォーマットおよび出力フォーマットの一覧は、
こちらで確認できます。
サポートされている ClickHouse データ型
対応する JS 型は、すべてを文字列として表現するもの (例: JSONStringEachRow) を除くすべての JSON* フォーマットに当てはまります
| Type | Status | JS type |
|---|
| UInt8/16/32 | ✔️ | number |
| UInt64/128/256 | ✔️ ❗- 以下を参照 | string |
| Int8/16/32 | ✔️ | number |
| Int64/128/256 | ✔️ ❗- 以下を参照 | string |
| Float32/64 | ✔️ | number |
| Decimal | ✔️ ❗- 以下を参照 | number |
| Boolean | ✔️ | boolean |
| String | ✔️ | string |
| FixedString | ✔️ | string |
| UUID | ✔️ | string |
| Date32/64 | ✔️ | string |
| DateTime32/64 | ✔️ ❗- 以下を参照 | string |
| Enum | ✔️ | string |
| LowCardinality | ✔️ | string |
| Array(T) | ✔️ | T[] |
| (new) JSON | ✔️ | object |
| Variant(T1, T2…) | ✔️ | T (バリアントによって異なる) |
| Dynamic | ✔️ | T (バリアントによって異なる) |
| Nested | ✔️ | T[] |
| Tuple(T1, T2, …) | ✔️ | [T1, T2, …] |
| Tuple(n1 T1, n2 T2…) | ✔️ | { n1: T1; n2: T2; …} |
| Nullable(T) | ✔️ | T に対応する JS 型または null |
| IPv4 | ✔️ | string |
| IPv6 | ✔️ | string |
| Point | ✔️ | [ number, number ] |
| Ring | ✔️ | Array<Point> |
| Polygon | ✔️ | Array<Ring> |
| MultiPolygon | ✔️ | Array<Polygon> |
| Map(K, V) | ✔️ | Record<K, V> |
| Time/Time64 | ✔️ | string |
サポートされている ClickHouse フォーマットの完全な一覧は
こちらで確認できます。
関連項目:
クライアントは追加の型変換を行わずに値を挿入するため、Date/Date32 型のカラムに挿入できるのは文字列のみです。
例: Date 型の値を挿入します。
ソースコード
await client.insert({
table: 'my_table',
values: [ { date: '2022-09-05' } ],
format: 'JSONEachRow',
})
ただし、DateTime または DateTime64 のカラムを使用している場合は、文字列と JS の Date オブジェクトの両方を使用できます。date_time_input_format を best_effort に設定すると、JS の Date オブジェクトをそのまま insert に渡せます。詳細については、こちらの例を参照してください。
JSON* 系のフォーマットを使って Decimal を挿入できます。たとえば、次のように定義されたテーブルがあるとします。
CREATE TABLE my_table
(
id UInt32,
dec32 Decimal(9, 2),
dec64 Decimal(18, 3),
dec128 Decimal(38, 10),
dec256 Decimal(76, 20)
)
ENGINE MergeTree()
ORDER BY (id)
文字列として表現すれば、精度を失うことなく値を挿入できます。
await client.insert({
table: 'my_table',
values: [{
id: 1,
dec32: '1234567.89',
dec64: '123456789123456.789',
dec128: '1234567891234567891234567891.1234567891',
dec256: '12345678912345678912345678911234567891234567891234567891.12345678911234567891',
}],
format: 'JSONEachRow',
})
ただし、JSON* フォーマットでデータをクエリする場合、ClickHouse はデフォルトで Decimal を数値として返すため、精度が失われる可能性があります。これを避けるには、クエリ内で Decimal を文字列に CAST できます。
await client.query({
query: `
SELECT toString(dec32) AS decimal32,
toString(dec64) AS decimal64,
toString(dec128) AS decimal128,
toString(dec256) AS decimal256
FROM my_table
`,
format: 'JSONEachRow',
})
詳しくは、この例を参照してください。
整数型: Int64, Int128, Int256, UInt64, UInt128, UInt256
サーバーはこれを数値として受け取れますが、これらの型の最大値は Number.MAX_SAFE_INTEGER より大きいため、
整数のオーバーフローを避けるため、JSON* 系の出力フォーマットでは文字列として返されます。
ただし、この動作は
output_format_json_quote_64bit_integers 設定
で変更できます。
例: 64 ビット整数の JSON 出力フォーマットを調整します。
const resultSet = await client.query({
query: 'SELECT * from system.numbers LIMIT 1',
format: 'JSONEachRow',
})
expect(await resultSet.json()).toEqual([ { number: '0' } ])
const resultSet = await client.query({
query: 'SELECT * from system.numbers LIMIT 1',
format: 'JSONEachRow',
clickhouse_settings: { output_format_json_quote_64bit_integers: 0 },
})
expect(await resultSet.json()).toEqual([ { number: 0 } ])
クライアントは、settings
の仕組みを通じて ClickHouse の動作を調整できます。
これらの settings はクライアントのインスタンスレベルで設定でき、ClickHouse に送信される
すべてのリクエストに適用されます。
const client = createClient({
clickhouse_settings: {}
})
また、設定はリクエストレベルで指定することもできます。
client.query({
clickhouse_settings: {}
})
サポートされているすべての ClickHouse 設定を含む型宣言ファイルは、
こちらで確認できます。
クエリを実行するユーザーに、設定を変更するための十分な権限があることを確認してください。
パラメータ付きのクエリを作成し、クライアントアプリケーションからその値を渡すことができます。これにより、クライアント側で
特定の動的な値を使ってクエリをフォーマットする必要がなくなります。
通常どおりにクエリを記述し、次に、アプリのパラメータからクエリに渡したい値を、以下の
形式で波かっこ内に配置します。
以下:
name — プレースホルダーの識別子。
data_type - アプリパラメータの値のデータ型。
例: パラメータを指定したクエリ。
ソースコード
.
await client.query({
query: 'SELECT plus({val1: Int32}, {val2: Int32})',
format: 'CSV',
query_params: {
val1: 10,
val2: 20,
},
})
詳しくは、https://clickhouse.com/docs/interfaces/cli#cli-queries-with-parameters-syntax を参照してください。
注: 現時点では、リクエストの圧縮は Web 版では利用できません。レスポンスの圧縮は通常どおり機能します。Node.js 版では両方がサポートされています。
ネットワーク経由で大規模なデータを扱うデータアプリケーションでは、圧縮を有効にすることでメリットが得られます。現在サポートされているのは、zlib を使用する GZIP のみです。
createClient({
compression: {
response: true,
request: true
}
})
設定パラメータは次のとおりです:
response: true は、ClickHouseサーバーが圧縮されたレスポンスボディを返すよう指定します。デフォルト値: response: false
request: true は、クライアントのリクエストボディの圧縮を有効にします。デフォルト値: request: false
ログは実験的な機能であり、今後変更される可能性があります。
デフォルトのロガー実装では、console.debug/info メソッドを通じてログレコードを stdout に、console.warn/error メソッドを通じて stderr に出力します。
LoggerClass を指定することでログ出力のロジックをカスタマイズでき、level パラメーターで必要なログレベルを選択できます (デフォルトは WARN) :
import type { Logger } from '@clickhouse/client'
// 3つのLogParamsタイプはすべてクライアントからエクスポートされます
interface LogParams {
module: string
message: string
args?: Record<string, unknown>
}
type ErrorLogParams = LogParams & { err: Error }
type WarnLogParams = LogParams & { err?: Error }
class MyLogger implements Logger {
trace({ module, message, args }: LogParams) {
// ...
}
debug({ module, message, args }: LogParams) {
// ...
}
info({ module, message, args }: LogParams) {
// ...
}
warn({ module, message, args }: WarnLogParams) {
// ...
}
error({ module, message, args, err }: ErrorLogParams) {
// ...
}
}
const client = createClient({
log: {
LoggerClass: MyLogger,
level: ClickHouseLogLevel.DEBUG,
}
})
現在、クライアントは次のイベントをログに出力します。
TRACE - Keep-Alive ソケットのライフサイクルに関する低レベルの情報
DEBUG - レスポンス情報 (認可ヘッダーとホスト情報を除く)
INFO - ほとんど使われません。クライアントの初期化時に現在のログレベルを出力します
WARN - 致命的ではない error。ping リクエストの失敗は警告として記録されます。これは、根本原因の error が返される結果に含まれているためです
ERROR - リクエスト失敗など、query/insert/exec/command メソッドで発生した致命的な error
デフォルトのロガー実装はこちらで確認できます。
Node.js client は、basic (証明機関のみ) TLS と
mutual (証明機関とクライアント証明書) TLS の両方をオプションでサポートしています。
証明書を certs フォルダーに配置し、
CA ファイル名が CA.pem である場合の basic TLS 構成例を次に示します:
const client = createClient({
url: 'https://<hostname>:<port>',
username: '<username>',
password: '<password>', // 必要な場合
tls: {
ca_cert: fs.readFileSync('certs/CA.pem'),
},
})
クライアント証明書を使用する相互TLS設定の例:
const client = createClient({
url: 'https://<hostname>:<port>',
username: '<username>',
tls: {
ca_cert: fs.readFileSync('certs/CA.pem'),
cert: fs.readFileSync(`certs/client.crt`),
key: fs.readFileSync(`certs/client.key`),
},
})
リポジトリにある basic および mutual TLS の完全な実装例を参照してください。
Keep-Alive の設定 (Node.js のみ)
クライアントでは、基盤となる HTTP agent でデフォルトで Keep-Alive が有効になっています。つまり、確立済みのソケットは後続のリクエストで再利用され、Connection: keep-alive ヘッダーが送信されます。アイドル状態のソケットは、デフォルトでは 2500 ミリ秒の間、接続プール内に保持されます (このオプションの調整に関する注記 を参照してください) 。
keep_alive.idle_socket_ttl の値は、サーバー/LB の設定より十分に低くする必要があります。主な理由は、HTTP/1.1 ではサーバーがクライアントに通知せずにソケットを閉じることがあるため、サーバーまたはロードバランサーがクライアント より先に 接続を閉じると、クライアントが閉じられたソケットを再利用しようとして、socket hang up エラーが発生する可能性があるからです。
keep_alive.idle_socket_ttl を変更する場合は、常にサーバー/LB の Keep-Alive 設定と整合している必要があり、かつそれより 必ず小さく 設定する必要があることに注意してください。これにより、サーバーが開いている接続を先に閉じることがないようにできます。
クライアントでは、keep_alive.idle_socket_ttl を 2500 ミリ秒に設定しています。これは、最も安全なデフォルト値と考えられるためです。サーバー側では、config.xml を変更しなくても、ClickHouse 23.11 より前のバージョンでは keep_alive_timeout が最短 3 秒に設定される場合があります。
パフォーマンスに満足しており、問題も発生していない場合は、keep_alive.idle_socket_ttl 設定の値を増やさないことを推奨します。値を増やすと、“Socket hang-up” エラーが発生する可能性があるためです。さらに、アプリケーションが大量のクエリを送信し、それらの間の待機時間がそれほど長くない場合は、ソケットが十分長くアイドル状態にならず、クライアントがコネクションプール内に保持し続けるため、デフォルト値で十分です。
適切な Keep-Alive タイムアウト値は、次のコマンドを実行してサーバーのレスポンスヘッダーを確認することで取得できます。
curl -is --data-binary "SELECT 1" <clickhouse_url>
レスポンスのConnectionヘッダーとKeep-Aliveヘッダーの値を確認してください。たとえば、次のようになります。
Connection: Keep-Alive
Keep-Alive: timeout=10
この場合、keep_alive_timeout は 10 秒なので、アイドル状態のソケットを既定より少し長く開いたままにするために、keep_alive.idle_socket_ttl を 9000、あるいは 9500 ミリ秒まで増やしてみてください。サーバーがクライアントより先に接続を閉じていることを示す “Socket hang-up” エラーが発生しないか注意して確認し、エラーが出なくなるまで値を下げてください。
クライアントの最新バージョンを使用していても socket hang up エラーが発生する場合は、この問題を解決するために次の方法を試せます。
-
少なくとも
WARN のログレベル (デフォルト) でログを有効にしてください。これにより、application code 内に未消費の stream やぶら下がったままの stream がないか確認できます。これらは server 側でソケットが閉じられる原因になり得るため、transport layer が WARN レベルでログに記録します。クライアント設定では、次のようにログを有効にできます。
const client = createClient({
log: { level: ClickHouseLogLevel.WARN },
})
-
意図した設定が正しいクライアントのインスタンスに適用されていることを確認してください。アプリケーション内に複数のクライアントのインスタンスがある場合は、queries に使用しているインスタンスに正しい
keep_alive.idle_socket_ttl 値が設定されていることを再確認してください。
-
クライアント設定の
keep_alive.idle_socket_ttl を 500 ミリ秒短くしてください。状況によっては、たとえばクライアントと server の間の network latency が高い場合に、server が閉じようとしているソケットを送信リクエストが取得してしまう状況を避けられるため、有効なことがあります。
-
このエラーが、データの入出力がない長時間実行クエリ (たとえば長時間実行される
INSERT FROM SELECT) の実行中に発生している場合、load balancer やその他のネットワーク components が長時間維持される connection や長時間実行リクエストを閉じている可能性があります。次の ClickHouse settings を組み合わせて使い、長時間実行クエリの実行中にも何らかのデータが流れるようにしてみてください。
const client = createClient({
// ここでは、実行時間が 5 分を超える queries が存在すると仮定しています
request_timeout: 400_000,
/** これらの settings を組み合わせることで、データの入出力がない長時間実行クエリにおける LB の timeout 問題を回避できます。
* `INSERT FROM SELECT` などでは、connection が LB によって idle と見なされ、突然閉じられる可能性があります。
* この例では、LB の idle connection timeout が 120 秒であると仮定し、安全な値として 110 秒を設定しています。 */
clickhouse_settings: {
send_progress_in_http_headers: 1,
http_headers_progress_interval_ms: '110000', // UInt64。文字列として渡す必要があります
},
})
ただし、最近の Node.js バージョンでは、受信した headers の合計サイズに 16KB の上限がある点に注意してください。一定数の progress headers を受信すると (私たちのテストでは約 70~80 個) 、例外が発生します。
また、wire 上での待ち時間を完全になくす、まったく別のアプローチを使うこともできます。これは、connection が失われても mutations はキャンセルされないという HTTP interface の「feature」を活用する方法です。詳しくは この例 (パート 2) を参照してください。
-
Keep-Alive 機能は完全に無効化することもできます。この場合、クライアントは各リクエストに
Connection: close header も追加し、基盤となる HTTP agent は connections を再利用しません。idling sockets がなくなるため、keep_alive.idle_socket_ttl 設定は無視されます。その結果、リクエストごとに新しい connection が確立されるため、追加のオーバーヘッドが発生します。
const client = createClient({
keep_alive: {
enabled: false,
},
})
-
curl などを使って、同じ ClickHouse インスタンスと同じネットワーク経路 (つまり同じマシンまたはネットワークセグメント、たとえば Kubernetes ポッド) で単純なコマンドラインテストを実行し、Node.js 自体を含むネットワークスタックの残りの部分に潜在的な問題がないか切り分けてください。
curl -is --user '<user>:<password>' --data-binary "SELECT 1" <clickhouse_url>
数分間ループで実行してみるとよいでしょう。curl でも同様のエラーが見られる場合、問題はクライアント設定ではなく、ネットワークスタックまたは server configuration にある可能性が高いです。
-
素の Node.js 機能で connection をテストするには、組み込みの
fetch API を使用して ClickHouse server に単純な HTTP request を作成してみてください。
const response = await fetch('<clickhouse_url>?query=SELECT+1', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('<user>:<password>').toString('base64'),
}
})
-
場合によっては、アプリケーションコードやフレームワークのアダプターが、実際のクエリ実行前に先行して
ping() を追加することがあります。その結果、ping() リクエストは成功しても、アイドル接続に関する同じ根本原因により、後続のクエリリクエストが “socket hang up” エラーで失敗することがあります。ログにそのようなパターンが見られる場合は、フレームワークまたはアプリケーションコードで先行 ping を無効にするオプションがないか確認してください。これは、途中のネットワークコンポーネントによってレート制限を受ける可能性を下げるのにも役立ちます。
-
アプリケーション自体に十分な CPU 時間が割り当てられており、ネットワークがホスティングプロバイダーによってスロットルされていないことを確認してください。GC pause メトリクス、event loop lag メトリクスなど、各種の監視手段も、潜在的なリソース不足の問題を切り分けるうえで役立ちます。
-
no-floating-promises ESLint rule を有効にして、アプリケーションコードを確認してみてください。これにより、ぶら下がったままのストリームやソケットにつながる可能性がある、未処理の Promise を特定しやすくなります。
クライアントを readonly=1 ユーザー で使用する場合、enable_http_compression 設定が必要になるため、レスポンスの圧縮は有効にできません。次の設定ではエラーが発生します。
const client = createClient({
compression: {
response: true, // readonly=1 ユーザーでは動作しません
},
})
readonly=1 ユーザーの制限事項についてさらに詳しく説明している例を参照してください。
ClickHouse インスタンスがプロキシの背後にあり、URL にたとえば http://proxy:8123/clickhouse_server のようなパス名が含まれている場合は、pathname 設定オプションに clickhouse_server を指定してください (先頭のスラッシュの有無は問いません) 。これを url に直接指定すると、database オプションとして解釈されます。複数のセグメントにも対応しており、たとえば /my_proxy/db のように指定できます。
const client = createClient({
url: 'http://proxy:8123',
pathname: '/clickhouse_server',
})
ClickHouseデプロイの前段に認証付きのリバースプロキシがある場合は、http_headers 設定を使用して、そこで必要なヘッダーを指定できます。
const client = createClient({
http_headers: {
'My-Auth-Header': '...',
},
})
カスタム HTTP/HTTPS エージェント (実験的、Node.js のみ)
これは実験的な機能であり、今後のリリースで後方互換性のない変更が加えられる可能性があります。クライアントが提供するデフォルト実装と設定で、ほとんどのユースケースには十分対応できます。この機能は、本当に必要だと確信できる場合にのみ使用してください。
デフォルトでは、クライアントはクライアント設定 (max_open_connections、keep_alive.enabled、tls など) に基づいて、基盤となる HTTP または HTTPS エージェントを構成し、それが ClickHouse server への接続を処理します。さらに、TLS 証明書を使用する場合は、基盤となるエージェントに必要な証明書が設定され、適切な TLS 認証ヘッダーが適用されます。
1.2.0 以降では、カスタム HTTP または HTTPS エージェントをクライアントに渡して、デフォルトの基盤エージェントを置き換えることができます。これは、複雑なネットワーク構成で役立つ場合があります。カスタムエージェントが指定されている場合は、次の条件が適用されます。
max_open_connections と tls オプションは基盤エージェントの設定の一部であるため、効果はなく、クライアントによって無視されます。
keep_alive.enabled は、Connection ヘッダーのデフォルト値 (true -> Connection: keep-alive、false -> Connection: close) のみを制御します。
- アイドル状態の keep-alive ソケット管理は引き続き機能しますが (これはエージェントではなく個々のソケット自体に紐づいているため) 、
keep_alive.idle_socket_ttl の値を 0 に設定することで、これを完全に無効化できるようになりました。
証明書を使用しないカスタム HTTP または HTTPS Agent の例:
const agent = new http.Agent({ // または https.Agent
keepAlive: true,
keepAliveMsecs: 2500,
maxSockets: 10,
maxFreeSockets: 10,
})
const client = createClient({
http_agent: agent,
})
basic TLS と CA 証明書を使用したカスタム HTTPS Agent:
const agent = new https.Agent({
keepAlive: true,
keepAliveMsecs: 2500,
maxSockets: 10,
maxFreeSockets: 10,
ca: fs.readFileSync('./ca.crt'),
})
const client = createClient({
url: 'https://myserver:8443',
http_agent: agent,
// カスタムHTTPSエージェントを使用する場合、クライアントはデフォルトのHTTPS接続実装を使用しません。ヘッダーは手動で指定する必要があります
http_headers: {
'X-ClickHouse-User': 'username',
'X-ClickHouse-Key': 'password',
},
// 重要: 認証ヘッダーはTLSヘッダーと競合します。無効にしてください。
set_basic_auth_header: false,
})
相互 TLS で custom HTTPS Agent を使用する:
const agent = new https.Agent({
keepAlive: true,
keepAliveMsecs: 2500,
maxSockets: 10,
maxFreeSockets: 10,
ca: fs.readFileSync('./ca.crt'),
cert: fs.readFileSync('./client.crt'),
key: fs.readFileSync('./client.key'),
})
const client = createClient({
url: 'https://myserver:8443',
http_agent: agent,
// カスタムHTTPSエージェントを使用する場合、クライアントはデフォルトのHTTPS接続実装を使用しません。ヘッダーは手動で指定する必要があります
http_headers: {
'X-ClickHouse-User': 'username',
'X-ClickHouse-Key': 'password',
'X-ClickHouse-SSL-Certificate-Auth': 'on',
},
// 重要: 認証ヘッダーはTLSヘッダーと競合します。無効にしてください。
set_basic_auth_header: false,
})
証明書 と カスタムの HTTPS Agent を併用する場合、TLS ヘッダーと競合するため、set_basic_auth_header 設定 (1.2.0 で導入) を使ってデフォルトの Authorization ヘッダーを無効にする必要がある可能性があります。TLS ヘッダーはすべて手動で指定する必要があります。
select クエリではストリーミングは機能しますが、insert では無効になっています (型レベルでも同様です) 。
- リクエストの圧縮は無効になっており、設定は無視されます。レスポンスの圧縮は機能します。
- まだログには対応していません。
- アプリケーションのメモリ使用量を減らすには、大量の insert (例: ファイルからの insert) や、該当する場合は select でストリームを使用することを検討してください。イベントリスナーなどのユースケースでは、クライアント側でのバッチ化を最小限に抑えたり、場合によっては完全に不要にしたりできるため、非同期 INSERT も有力な選択肢です。非同期 INSERT の例は クライアントリポジトリ にあり、ファイル名のプレフィックスは
async_insert_ です。
- クライアントでは、リクエストやレスポンスの圧縮はデフォルトで有効になっていません。ただし、大規模なデータセットを select または insert する場合は、
ClickHouseClientConfigOptions.compression で有効化を検討できます (request のみ、response のみ、またはその両方) 。
- 圧縮には無視できないパフォーマンス低下があります。
request または response に対して有効にすると、それぞれ insert または select の速度に悪影響がありますが、アプリケーションが転送するネットワークトラフィック量は削減できます。
ご質問やサポートが必要な場合は、Community Slack (#clickhouse-js チャンネル) または GitHub issues までお気軽にご連絡ください。