@clickhouse/client- Node.js のみ@clickhouse/client-web- ブラウザー (Chrome/Firefox) 、Cloudflare workers
AI agent スキルJS client には、コーディング agents が client を利用する際に役立つ AI agent スキルが付属しています。次のコマンドでインストールしてください。
環境要件 (node.js)
環境要件 (Web 版)
インストール
ClickHouse との互換性
古いバージョンのクライアントでも動作する可能性はありますが、これはベストエフォートでのサポートであり、動作は保証されません。23.3 より前の ClickHouse バージョンを使用している場合は、ClickHouse security policy を参照し、アップグレードを検討してください。
例
クライアント API
クライアントインスタンスの作成
createClient ファクトリーを使用すると、必要な数のクライアントインスタンスを作成できます。
設定
Node.js 固有の設定パラメータ
URL 設定
http[s]://[username:password@]hostname:port[/database][?param1=value1¶m2=value2] です。ほとんどの場合、個々のパラメータ名は config options interface 内でのパスを反映していますが、いくつか例外があります。次のパラメータがサポートされています。
- (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)
http_header設定についても (2) と同様です。たとえば、?http_header_x-clickhouse-auth=foobarは次と同等です。
接続
接続情報を確認する
ClickHouse Cloud サービスの詳細は、ClickHouse Cloud コンソールで確認できます。
サービスを選択し、Connect をクリックします。
HTTPS を選択します。接続情報は
curl コマンドの例として表示されます。
セルフマネージド ClickHouse を使用している場合、接続情報は ClickHouse 管理者によって設定されます。
接続の概要
url (プロトコルとポートを含む) および password の値は環境変数で指定し、default ユーザーを使用することを前提としています。
例: 設定に環境変数を使用して Node.js クライアントインスタンスを作成します。
接続プール (Node.js のみ)
10 に設定されていますが、設定オプション max_open_connections で変更できます。
ユーザーが max_open_connections: 1 を設定しない限り、後続のクエリでプール内の同じ接続が使用される保証はありません。これは必要になることはほとんどありませんが、一時テーブルを使用する場合には必要になることがあります。
関連項目: Keep-Alive 設定。
クエリ ID
command、exec、insert、select) では、結果に query_id が含まれます。この一意の識別子はクライアントによってクエリごとに割り当てられ、サーバー設定 で有効になっていれば system.query_log からデータを取得したり、長時間実行されているクエリをキャンセルしたりする際に役立つことがあります (例 を参照) 。必要に応じて、query_id は command/query/exec/insert メソッドのパラメーターでユーザーが上書きできます。
Base parameters for all client methods
クエリメソッド
SELECT のように応答を返すほとんどのステートメントや、CREATE TABLE のような DDL の送信に使用し、await する必要があります。返された結果セットは、アプリケーション側で処理することが想定されています。
結果セットと行の抽象化
ResultSet には、アプリケーションでのデータ処理に便利ないくつかのメソッドが用意されています。
Node.js の ResultSet 実装は内部で Stream.Readable を使用し、Web 版は Web API の ReadableStream を使用します。
ResultSet は、ResultSet の text または json メソッドを呼び出して消費でき、クエリが返した行セット全体をメモリに読み込めます。
ResultSet はレスポンスストリームを開いたまま保持し、その結果として基盤となる接続を占有し続けるため、できるだけ早く消費を開始してください。クライアントは、アプリケーションで過剰なメモリ使用量が発生するのを避けるため、受信データをバッファリングしません。
また、一度にメモリに収まらないほど大きい場合は、stream メソッドを呼び出してストリーミングモードでデータを処理できます。この場合、各レスポンス chunk は比較的小さな行の配列に変換されて処理されます (この配列のサイズは、クライアントがサーバーから受信する chunk のサイズ (可変) と、個々の行のサイズによって決まります) 。これを 1 chunk ずつ処理します。
ご利用のケースでストリーミングに最適なフォーマットを判断するには、サポートされているデータフォーマット の一覧を参照してください。たとえば、JSON オブジェクトをストリーミングしたい場合は JSONEachRow を選択でき、その場合は各行が JS オブジェクトとして解析されます。あるいは、よりコンパクトな JSONCompactColumns フォーマットを選ぶこともでき、この場合は各行が値のコンパクトな配列になります。関連項目: ファイルのストリーミング。
JSONEachRow フォーマットの結果データセットを返すクエリ。ストリーム全体を消費し、内容を JS オブジェクトとしてパースします。
ソースコード.
on('data') アプローチを使って、JSONEachRow フォーマットでクエリ結果をストリーミングする例です。これは for await const 構文でも同様に実現できます。ソースコード。
on('data') アプローチを使って、クエリ結果を CSV フォーマットでストリーミングします。これは for await const 構文でも同様に実装できます。
ソースコード
for await const 構文を使用して、JSONEachRow フォーマットのクエリ結果を JS オブジェクトとしてストリーミングで処理する例です。これは従来の on('data') アプローチと同様に使用できます。
ソースコード.
for await const 構文は on('data') を使う方法よりコード量をやや減らせますが、パフォーマンスに悪影響を与える可能性があります。
詳細については、Node.js リポジトリのこの issueを参照してください。ReadableStream をイテレーション処理する例。
Insertメソッド
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の利用を検討してください。
Web 版の制限事項
@clickhouse/client-web での insert は、Array<T> および JSON* フォーマットでのみ利用できます。
ブラウザの互換性の問題により、Web 版ではストリームの insert はまだサポートされていません。
そのため、Web 版の InsertParams インターフェイスは Node.js 版とは少し異なり、
values は ReadonlyArray<T> 型にのみ制限されています:
Command メソッド
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 only)
ファイルのストリーミング (Node.js のみ)
query 呼び出しで使用するフォーマット (JSONEachRow、CSV など) と出力ファイル名だけです。
サポートされているデータフォーマット
format に JSON 系のフォーマット (JSONEachRow、JSONCompactEachRow など) を指定すると、クライアントは通信時にデータをシリアライズおよびデシリアライズします。
「raw」テキストフォーマット (CSV、TabSeparated、CustomSeparated 系) で指定したデータは、追加の変換なしでそのまま送信されます。
Parquet では、select の主な用途は、結果のストリームをファイルに書き出すことになるでしょう。クライアントリポジトリのこの例を参照してください。
JSONEachRowWithProgress は、ストリーム内での進捗レポートをサポートする出力専用のフォーマットです。詳しくは、この例を参照してください。
ClickHouse の入力フォーマットおよび出力フォーマットの一覧は、
こちらで確認できます。
サポートされている ClickHouse データ型
対応する JS 型は、すべてを文字列として表現するもの (例:
JSONStringEachRow) を除くすべての JSON* フォーマットに当てはまります
サポートされている ClickHouse フォーマットの完全な一覧は
こちらで確認できます。
関連項目:
Date/Date32 型の注意点
Date/Date32 型のカラムに挿入できるのは文字列のみです。
例: Date 型の値を挿入します。
ソースコード
DateTime または DateTime64 のカラムを使用している場合は、文字列と JS の Date オブジェクトの両方を使用できます。date_time_input_format を best_effort に設定すると、JS の Date オブジェクトをそのまま 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 settings
応用トピック
パラメータ付きクエリ
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 ミリ秒に設定しています。これは、最も安全なデフォルト値と考えられるためです。サーバー側では、config.xml を変更しなくても、ClickHouse 23.11 より前のバージョンでは keep_alive_timeout が最短 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やぶら下がったままのstreamがないか確認できます。これらは server 側でソケットが閉じられる原因になり得るため、transport layer が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 を組み合わせて使い、長時間実行クエリの実行中にも何らかのデータが流れるようにしてみてください。ただし、最近の Node.js バージョンでは、受信した headers の合計サイズに 16KB の上限がある点に注意してください。一定数の progress headers を受信すると (私たちのテストでは約 70~80 個) 、例外が発生します。 また、wire 上での待ち時間を完全になくす、まったく別のアプローチを使うこともできます。これは、connection が失われても mutations はキャンセルされないという HTTP interface の「feature」を活用する方法です。詳しくは この例 (パート 2) を参照してください。 -
Keep-Alive 機能は完全に無効化することもできます。この場合、クライアントは各リクエストに
Connection: closeheader も追加し、基盤となる HTTP agent は connections を再利用しません。idling sockets がなくなるため、keep_alive.idle_socket_ttl設定は無視されます。その結果、リクエストごとに新しい connection が確立されるため、追加のオーバーヘッドが発生します。 -
curlなどを使って、同じ ClickHouse インスタンスと同じネットワーク経路 (つまり同じマシンまたはネットワークセグメント、たとえば Kubernetes ポッド) で単純なコマンドラインテストを実行し、Node.js 自体を含むネットワークスタックの残りの部分に潜在的な問題がないか切り分けてください。数分間ループで実行してみるとよいでしょう。curlでも同様のエラーが見られる場合、問題はクライアント設定ではなく、ネットワークスタックまたは server configuration にある可能性が高いです。 -
素の Node.js 機能で connection をテストするには、組み込みの
fetchAPI を使用して ClickHouse server に単純な HTTP request を作成してみてください。
-
場合によっては、アプリケーションコードやフレームワークのアダプターが、実際のクエリ実行前に先行して
ping()を追加することがあります。その結果、ping()リクエストは成功しても、アイドル接続に関する同じ根本原因により、後続のクエリリクエストが “socket hang up” エラーで失敗することがあります。ログにそのようなパターンが見られる場合は、フレームワークまたはアプリケーションコードで先行pingを無効にするオプションがないか確認してください。これは、途中のネットワークコンポーネントによってレート制限を受ける可能性を下げるのにも役立ちます。 - アプリケーション自体に十分な CPU 時間が割り当てられており、ネットワークがホスティングプロバイダーによってスロットルされていないことを確認してください。GC pause メトリクス、event loop lag メトリクスなど、各種の監視手段も、潜在的なリソース不足の問題を切り分けるうえで役立ちます。
- no-floating-promises ESLint rule を有効にして、アプリケーションコードを確認してみてください。これにより、ぶら下がったままのストリームやソケットにつながる可能性がある、未処理の Promise を特定しやすくなります。
読み取り専用ユーザー
enable_http_compression 設定が必要になるため、レスポンスの圧縮は有効にできません。次の設定ではエラーが発生します。
パス名付きプロキシ
pathname 設定オプションに clickhouse_server を指定してください (先頭のスラッシュの有無は問いません) 。これを url に直接指定すると、database オプションとして解釈されます。複数のセグメントにも対応しており、たとえば /my_proxy/db のように指定できます。
認証付きリバースプロキシ
http_headers 設定を使用して、そこで必要なヘッダーを指定できます。
カスタム 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に設定することで、これを完全に無効化できるようになりました。
カスタムエージェントの使用例
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 でストリームを使用することを検討してください。イベントリスナーなどのユースケースでは、クライアント側でのバッチ化を最小限に抑えたり、場合によっては完全に不要にしたりできるため、非同期 INSERT も有力な選択肢です。非同期 INSERT の例は クライアントリポジトリ にあり、ファイル名のプレフィックスは
async_insert_です。 - クライアントでは、リクエストやレスポンスの圧縮はデフォルトで有効になっていません。ただし、大規模なデータセットを select または insert する場合は、
ClickHouseClientConfigOptions.compressionで有効化を検討できます (requestのみ、responseのみ、またはその両方) 。 - 圧縮には無視できないパフォーマンス低下があります。
requestまたはresponseに対して有効にすると、それぞれ insert または select の速度に悪影響がありますが、アプリケーションが転送するネットワークトラフィック量は削減できます。
お問い合わせ
#clickhouse-js チャンネル) または GitHub issues までお気軽にご連絡ください。