@clickhouse/client- Node.js のみ@clickhouse/client-web- ブラウザー (Chrome/Firefox) 、Cloudflare workers
AI agent スキルこの JS Client には、コーディングエージェントが Client を扱う際に役立つ AI agent スキルが含まれています。次のようにインストールしてください。
環境要件 (node.js)
環境要件 (Web 版)
インストール
ClickHouseとの互換性
このクライアントは古いバージョンでも動作する可能性がありますが、これはベストエフォートでのサポートであり、保証されるものではありません。ClickHouseのバージョンが23.3より古い場合は、ClickHouse のセキュリティポリシーを参照し、アップグレードを検討してください。
例
クライアント API
Clientインスタンスの作成
createClient ファクトリを使うと、必要な数のClientインスタンスを作成できます。
設定
Node.js 固有の設定パラメーター
URL設定
http[s]://[username:password@]hostname:port[/database][?param1=value1¶m2=value2] です。ほとんどの場合、各パラメータ名は設定オプションのインターフェイス内でのパスに対応していますが、いくつか例外があります。サポートされているパラメータは次のとおりです。
- (1) ブール値で有効な値は
true/1とfalse/0です。 - (2)
clickhouse_setting_またはch_で始まるパラメータは、このプレフィックスを取り除いたうえで、残りの部分がクライアントのclickhouse_settingsに追加されます。たとえば、?ch_async_insert=1&ch_wait_for_async_insert=1は次と同じです:
clickhouse_settings のブール値は、URL では 1/0 として指定する必要があります。
- (3) (2) と同様ですが、
http_headerの設定用です。たとえば、?http_header_x-clickhouse-auth=foobarは次と同等です。
接続
接続情報を用意する
ClickHouse Cloud サービスの詳細は、ClickHouse Cloud コンソールで確認できます。
サービスを選択し、Connect をクリックします。

curl コマンドの例として表示されます。

接続の概要
url (プロトコルとポートを含む) および password の値は環境変数で指定し、default ユーザーを使用することを前提としています。
例: 設定に環境変数を使用して Node.js のクライアントインスタンスを作成します。
接続プール (Node.js のみ)
10 に設定されていますが、設定オプション max_open_connections で変更できます。
ユーザーが max_open_connections: 1 を設定しない限り、プール内の同じ接続が後続のクエリでも使用されるとは限りません。これが必要になることはまれですが、一時テーブルを使用する場合には必要になることがあります。
関連項目: Keep-Alive の設定。
Query ID
command、exec、insert、select) は、結果に query_id を含みます。この一意の識別子はクエリごとにクライアントによって割り当てられ、サーバー設定 で有効になっていれば system.query_log からデータを取得したり、長時間実行中のクエリをキャンセルしたりする際に役立つ場合があります (例 を参照) 。必要に応じて、query_id は command/query/exec/insert メソッドのパラメータでユーザーが上書きできます。
すべてのクライアントメソッドに共通の基本パラメータ
クエリメソッド
SELECT のようにレスポンスを返すステートメントのほとんどや、CREATE TABLE のような DDL の送信に使用するメソッドで、await する必要があります。返された結果セットは、アプリケーション側で処理することが想定されています。
結果セットと行の抽象化
ResultSet には、アプリケーションでのデータ処理に便利なメソッドがいくつか用意されています。
Node.js の ResultSet 実装は内部で Stream.Readable を使用し、Web 版では Web API の ReadableStream を使用します。
ResultSet の text または json メソッドを呼び出すことで、クエリが返した行のセット全体をメモリに読み込んで処理できます。
ResultSet はレスポンスストリームを開いたまま保持するため、その間は基盤となる接続が使用中のままになります。そのため、できるだけ早く ResultSet の読み取りを開始してください。Clientは、アプリケーションのメモリ使用量が過大になる可能性を避けるため、受信データをバッファリングしません。
また、データが大きすぎて一度にメモリに収まらない場合は、stream メソッドを呼び出してストリーミングモードで処理できます。この場合、各レスポンス chunk は比較的小さな行の配列に変換され、1 回に 1 つの chunk ずつ処理されます (この配列のサイズは、Clientがサーバーから受信する chunk のサイズ (可変) と、個々の行のサイズに依存します) 。
どのフォーマットがこのケースのストリーミングに最適かを判断するには、サポートされているデータフォーマット の一覧を参照してください。たとえば、JSON オブジェクトをストリーミングしたい場合は、JSONEachRow を選ぶと、各行が JS オブジェクトとしてパースされます。あるいは、よりコンパクトな JSONCompactColumns フォーマットを選べば、各行はコンパクトな値の配列になります。関連項目: ファイルのストリーミング。
JSONEachRow フォーマットのクエリで、ストリーム全体を消費し、その内容を JS オブジェクトとしてパースします。
ソースコード.
on('data') アプローチを使って、JSONEachRow フォーマットのクエリ結果をストリーミングする例です。これは for await const 構文でも同様に実装できます。ソースコード。
on('data') アプローチを使って、CSV フォーマットのクエリ結果をストリーミングで取得する例です。これは for await const 構文に置き換えることもできます。
ソースコード
JSONEachRow フォーマットのストリーミングクエリ結果を JS オブジェクトとして for await const 構文で処理します。これは従来の on('data') アプローチと同じように使用できます。
ソースコード.
for await const 構文は on('data') を使う方法よりコード量をやや減らせますが、パフォーマンスに悪影響を与える可能性があります。
詳細は、Node.js リポジトリのこの issue を参照してください。ReadableStream を反復処理する例です。
Insert メソッド
insert メソッドに渡された場合、insert ステートメントはサーバーに送信されません。代わりに、メソッドはただちに { query_id: '...', executed: false } を返して resolve されます。この場合、query_id がメソッドの params で指定されていなければ、結果では空文字列になります。クライアントが生成したランダムな UUID を返すとかえって混乱を招く可能性があるためです。というのも、そのような query_id を持つクエリは system.query_log テーブルには存在しないからです。
insert ステートメントがサーバーに送信された場合、executed フラグは true になります。
Node.js における Insert メソッドとストリーミング
insert メソッドで指定するデータフォーマットに応じて、Stream.Readable と通常の Array<T> のどちらも使用できます。file streaming に関するこのセクションも参照してください。
Insert メソッドは await して使用することを前提としています。ただし、入力ストリームを指定しておき、そのストリームの完了後に insert 操作を await することも可能です (この時点で insert の Promise も resolve されます) 。これはイベントリスナーなどの用途では有用な場合がありますが、エラーハンドリングは簡単ではなく、クライアント側でさまざまなエッジケースへの対応が必要になる可能性があります。代わりに、この例で示しているように、非同期 INSERTの利用を検討してください。
Web 版の制限
@clickhouse/client-web では、insert は Array<T> および JSON* フォーマットでのみ利用できます。
ブラウザの互換性が十分でないため、Web 版ではストリーム挿入はまだサポートされていません。
そのため、Web 版の InsertParams インターフェイスは Node.js 版と少し異なり、
values に指定できるのは ReadonlyArray<T> 型のみです:
command メソッド
FORMAT 句を適用できない場合、あるいはレスポンス自体が不要な場合に使用できます。そのようなステートメントの例としては、CREATE TABLE や ALTER TABLE があります。
await する必要があります。
レスポンスストリームは直ちに破棄されるため、基盤となるソケットは解放されます。
Exec メソッド
query/insert に当てはまらないカスタムクエリがあり、
その結果を扱いたい場合は、command の代わりに exec を使用できます。
exec は、アプリケーション側で必ず消費または破棄する必要がある、読み取り可能なストリームを返します。
Ping
ping メソッドは、サーバーに到達できる場合に true を返します。
サーバーに到達できない場合は、原因となったエラーも結果に含まれます。
/ping エンドポイントを使用します。一方、Web 版は /ping エンドポイントが CORS をサポートしていないため、同様の結果を得るために単純な SELECT 1 クエリを使用します。
例: (Node.js/Web) ClickHouse サーバーインスタンスに対するシンプルな ping。注: Web 版では、キャッチされるエラーは異なります。
ソースコード.
pingメソッドの呼び出し時に認証情報も確認したい場合や、query_idなどの追加パラメータを指定したい場合は、次のように使用できます。
query メソッドのパラメータのほとんどを利用できます。PingParamsWithSelectQuery の型定義を参照してください。
Close (Node.js のみ)
ファイルストリーミング (Node.js のみ)
query 呼び出しで使用するフォーマット (JSONEachRow、CSV など) と出力ファイル名だけです。
サポートされるデータフォーマット
format に JSON 系のフォーマット (JSONEachRow、JSONCompactEachRow など) のいずれかを指定すると、クライアントは通信時にデータを serialize / deserialize します。
「raw」テキストフォーマット (CSV、TabSeparated、CustomSeparated 系) で提供されたデータは、追加の変換を行わずにそのまま送信されます。
Parquet では、SELECT の主な用途として考えられるのは、結果のストリームをファイルに書き出すことです。クライアントリポジトリの例を参照してください。
JSONEachRowWithProgress は、ストリーム内で進捗を報告できる出力専用フォーマットです。詳しくはこの例を参照してください。
ClickHouse の入力および出力フォーマットの一覧は、
こちらで確認できます。
サポートされている ClickHouse データ型
対応する JS 型は、すべてを文字列として表現するもの (例:
JSONStringEachRow) を除く JSON* フォーマットで該当します
サポートされている ClickHouse フォーマットの一覧は
こちらを参照してください。
関連項目:
Date/Date32 型の注意点
Date/Date32 型のカラムには文字列としてしか挿入できません。
例: Date 型の値を挿入します。
ソースコード
DateTime または DateTime64 カラムを使用している場合は、文字列と JS Date オブジェクトの両方を使用できます。JS Date オブジェクトは、date_time_input_format を best_effort に設定すれば、そのまま insert に渡せます。詳しくは、こちらの例を参照してください。
Decimal* 型の注意事項
JSON* ファミリーのフォーマットを使って Decimal を挿入できます。たとえば、次のようなテーブルが定義されているとします。
JSON*フォーマットでデータをクエリすると、ClickHouse はデフォルトで Decimal を数値として返すため、精度が失われる可能性があります。これを避けるには、クエリ内で Decimal を文字列に CAST できます。
整数型: Int64, Int128, Int256, UInt64, UInt128, UInt256
Number.MAX_SAFE_INTEGER を超えるため、
整数オーバーフローを避ける目的で、JSON* 系の出力フォーマットでは文字列として返されます。
ただし、この動作は
output_format_json_quote_64bit_integers 設定
で変更できます。
例: 64 ビット整数の JSON 出力フォーマットを調整します。
ClickHouse の設定
応用トピック
パラメータ付きクエリ
name— プレースホルダー識別子。data_type- アプリケーションパラメーター値のデータ型。
圧縮
GZIP のみです。
response: trueは、ClickHouseサーバーが圧縮されたレスポンスボディを返すようにします。デフォルト値:response: falserequest: trueは、クライアントのリクエストボディの圧縮を有効にします。デフォルト値:request: false
ロギング (Node.js のみ)
console.debug/info メソッド経由でログレコードを stdout に、console.warn/error メソッド経由で stderr に出力します。
LoggerClass を指定することでロギングの処理をカスタマイズでき、level パラメーターで任意のログレベルを選択できます (デフォルトは WARN) :
TRACE- Keep-Alive ソケットのライフサイクルに関する低レベルの情報DEBUG- レスポンス情報 (認証ヘッダーとホスト情報を除く)INFO- ほとんど使われません。クライアントの初期化時に現在のログレベルを出力しますWARN- 致命的でない error。pingリクエストの失敗は警告としてログに記録されます。これは、基になる error が戻り値に含まれているためですERROR- 失敗したリクエストなど、query/insert/exec/commandメソッドで発生する致命的な error
TLS 証明書 (Node.js のみ)
certs フォルダにあり、
CA ファイル名が CA.pem であると仮定した basic TLS の設定例:
Keep-Alive の設定 (Node.js のみ)
Connection: keep-alive ヘッダーが送信されます。アイドル状態のソケットは、デフォルトでは 2500 ミリ秒のあいだ接続プールに保持されます (このオプションの調整に関する注意事項 を参照) 。
keep_alive.idle_socket_ttl の値は、サーバー/LB の設定よりも十分に低くする必要があります。主な理由は、HTTP/1.1 ではサーバーがクライアントに通知せずにソケットを閉じられるため、サーバーまたはロードバランサーがクライアントより 先に 接続を閉じると、クライアントが閉じられたソケットを再利用しようとして、socket hang up エラーが発生する可能性があるからです。
keep_alive.idle_socket_ttl を変更する場合は、常にサーバー/LB の Keep-Alive 設定と整合している必要があり、さらにサーバーが開いている接続を先に閉じないよう、その値は 必ずそれより低く しなければならない点に注意してください。
idle_socket_ttl の調整
keep_alive.idle_socket_ttl を 2500 ミリ秒に設定しています。サーバー側の keep_alive_timeout は、config.xml を変更しなくても、ClickHouse 23.11 より前のバージョンでは 3 秒まで短く設定される場合があります。
次のコマンドを実行すると、サーバーのレスポンスヘッダーで正しい Keep-Alive タイムアウト値を確認できます。
ConnectionヘッダーとKeep-Aliveヘッダーの値を確認してください。たとえば、次のとおりです。
keep_alive_timeout は 10 秒なので、デフォルトより少し長くアイドル状態のソケットを開いたままにするために、keep_alive.idle_socket_ttl を 9000、あるいは 9500 ミリ秒に増やしてみてください。“Socket hang-up” エラーが発生していないか注意して確認してください。これは、クライアントより先にサーバーが接続を閉じていることを示します。エラーが出なくなるまで値を下げていってください。
トラブルシューティング
socket hang up エラーが発生する場合は、次の対処方法を試してください。
-
少なくとも
WARNのログレベル (デフォルト) でログを有効にしてください。これにより、application code 内に未消費または宙に浮いた stream がないか確認できます。こうした状態は server 側で socket が閉じられる原因になり得るため、transport layer が WARN レベルでログを出力します。client の設定でログを有効にするには、次のようにします。 -
意図した設定が正しいクライアントインスタンスに適用されていることを確認してください。アプリケーション内に複数の client instance がある場合は、queries に使用しているものに正しい
keep_alive.idle_socket_ttlの値が設定されているか再確認してください。 -
client 設定の
keep_alive.idle_socket_ttlを 500 ミリ秒短くしてください。状況によっては、たとえば client と server 間の network latency が高い場合、server がまもなく閉じる socket を送信リクエストが取得してしまう状況を避けるうえで有効です。 -
このエラーが、データの入出力がない長時間実行クエリ中 (たとえば長時間実行される
INSERT FROM SELECT) に発生する場合は、load balancer やその他の network components が長時間維持される connection や長時間実行中のリクエストを閉じている可能性があります。以下の ClickHouse settings を組み合わせて使い、長時間実行クエリ中にも何らかのデータが流入するようにしてみてください。ただし、最近の Node.js バージョンでは、受信した headers の合計サイズに 16KB の制限がある点に注意してください。一定数の progress headers を受信すると (私たちのテストではおよそ 70~80 個) 、Exception が発生します。 また、on the wire での待機時間を完全になくす、まったく別のアプローチを取ることも可能です。これは、connection が失われても mutations がキャンセルされないという HTTP interface の「feature」を利用する方法です。詳細は this example (part 2) を参照してください。 -
Keep-Alive 機能は完全に無効化することもできます。この場合、client はすべての request に
Connection: closeheader も追加し、基盤となる HTTP agent は connections を再利用しません。アイドル状態の sockets が存在しないため、keep_alive.idle_socket_ttl設定は無視されます。その結果、リクエストごとに新しい connection を確立することになり、追加の overhead が発生します。 -
curlなどを使って、同じ ClickHouse instance と同じ network path (つまり同じマシンまたは同じ network segment、たとえば Kubernetes pod から) で簡単な command-line テストを実行し、Node.js 自体を含む network stack の残りの部分に問題がないか切り分けてください。数分間ループで実行してみるとよいでしょう。curlでも同様のエラーが出る場合、問題は client 設定ではなく、network stack または server configuration にある可能性が高いです。 -
素の Node.js 機能で connection をテストするには、組み込みの
fetchAPI を使って ClickHouse server に対する単純な HTTP request を作成してみてください。
-
場合によっては、アプリケーションコードやフレームワークのアダプターが、実際のクエリ実行の前に
ping()を先行して送ることがあります。その結果、ping()リクエストは成功しても、後続のクエリリクエストが、アイドル接続に関する同じ根本原因によって “socket hang up” エラーで失敗することがあります。ログにそのパターンが見られる場合は、フレームワークやアプリケーションコードで先行ping()を無効化できるオプションがないか確認してみてください。これは、途中のネットワークコンポーネントによるレート制限を受ける可能性を下げるうえでも役立ちます。 - アプリケーション自体に十分な CPU time が割り当てられており、ネットワークがホスティングプロバイダーによって帯域制限されていないことを確認してください。GC pause メトリクスや event loop lag メトリクスなど、各種の監視手段も、リソース枯渇の可能性を切り分けるのに役立ちます。
- no-floating-promises ESLint ルールを有効にして、アプリケーションコードを確認してみてください。これにより、ストリームやソケットがぶら下がったままになる原因となる、未処理の Promise を特定しやすくなります。
読み取り専用ユーザー
enable_http_compression 設定が必要なため、有効にできません。次の設定ではエラーになります。
readonly=1 ユーザーの制限についてさらに詳しく説明している例を参照してください。
パス名付きプロキシ
http://proxy:8123/clickhouse_server のように URL にパス名が含まれている場合は、pathname 設定オプションに clickhouse_server を指定してください (先頭のスラッシュの有無は問いません) 。そうしないと、これを url に直接含めた場合、database オプションとして扱われます。複数のセグメントにも対応しており、たとえば /my_proxy/db のように指定できます。
認証付きリバースプロキシ
http_headers 設定を使って、そこで必要なヘッダーを指定できます。
カスタム HTTP/HTTPS エージェント (実験的、Node.js のみ)
max_open_connections、keep_alive.enabled、tls など) で指定された値を使って、ClickHouse server への接続を処理する基盤の HTTP または HTTPS エージェントを構成します。さらに、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に設定することで、これを完全に無効化できるようになりました。
カスタムエージェントの使用例
set_basic_auth_header 設定 (導入バージョン 1.2.0) でデフォルトの Authorization ヘッダーを無効にする必要がある可能性があります。TLS ヘッダーはすべて手動で指定する必要があります。
既知の制限事項 (Node.js/web)
- 結果セット用のデータマッパーは存在しないため、言語組み込みのプリミティブ型のみが使用されます。特定のデータ型マッパーについては、RowBinary フォーマットのサポートで対応が予定されています。
- Decimal* と Date* / DateTime* データ型に関する注意点がいくつかあります。
- JSON* ファミリーのフォーマットを使用する場合、Int64+ 型の最大値は
Number.MAX_SAFE_INTEGERを超えるため、Int32 を超える数値は文字列として表現されます。詳細は 整数型 セクションを参照してください。
既知の制限事項 (web)
selectクエリのストリーミングは動作しますが、insertでは無効になっています (型レベルでも同様です) 。- リクエストの圧縮は無効になっており、設定は無視されます。レスポンスの圧縮は動作します。
- ロギングにはまだ対応していません。
パフォーマンス最適化のヒント
- アプリケーションのメモリ消費を抑えるには、大規模な insert (たとえばファイルからの insert) や、該当する場合は select でストリームを使用することを検討してください。イベント listener や同様のユースケースでは、非同期 INSERT も有力な選択肢です。これにより、クライアント側でのバッチ化を最小限に抑えたり、完全に不要にしたりできます。非同期 INSERT の例は client repository にあり、ファイル名のプレフィックスとして
async_insert_が使われています。 - client は、デフォルトではリクエストまたはレスポンスの圧縮を有効にしていません。ただし、大規模なデータセットを select または insert する場合は、
ClickHouseClientConfigOptions.compressionで有効にすることを検討できます (requestのみ、responseのみ、またはその両方) 。 - 圧縮には大きな性能上のペナルティがあります。
requestまたはresponseに対して有効にすると、それぞれ insert または select の速度に悪影響を与えますが、アプリケーションで転送されるネットワークトラフィックの量は削減されます。
お問い合わせ
#clickhouse-js チャンネル) または GitHub issues からお気軽にご連絡ください。