@clickhouse/client- 仅限 Node.js@clickhouse/client-web- 浏览器 (Chrome/Firefox) 、Cloudflare workers
AI 智能体技能JavaScript 客户端附带了 AI 智能体技能,可帮助编程智能体使用该客户端。安装方式如下:
环境要求 (Node.js)
环境要求 (Web)
安装
与 ClickHouse 的兼容性
该客户端很可能也能在更早的版本上运行;不过,这类支持仅为尽力而为,不作保证。如果你使用的 ClickHouse 版本早于 23.3,请参阅 ClickHouse 安全策略 并考虑升级。
示例
客户端 API
创建客户端实例
createClient 工厂按需创建任意数量的客户端实例:
配置
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 配置。
查询 ID
command、exec、insert、select) 都会在结果中返回 query_id。这个唯一标识符由客户端为每个查询分配;如果在服务器配置中启用了 system.query_log,它可用于从中获取数据,
也可用于取消长时间运行的查询 (参见该示例) 。如有需要,用户也可以在 command/query/exec/insert 方法的 params 中覆盖 query_id。
Base parameters for all client methods
查询方法
SELECT,也可用于发送 DDL 语句 (如 CREATE TABLE) ,并且应使用 await 等待其完成。返回的结果集应在应用程序中进行处理。
结果集和行抽象
ResultSet 提供了多种便捷方法,便于在应用程序中处理数据。
Node.js 中的 ResultSet 实现底层使用 Stream.Readable,而 Web 版本使用 Web API ReadableStream。
你可以在 ResultSet 上调用 text 或 json 方法来消费 ResultSet,并将查询返回的全部行加载到内存中。
你应尽早开始消费 ResultSet,因为它会保持响应流处于打开状态,从而使底层连接始终处于忙碌状态。客户端不会缓冲传入的数据,以避免应用程序出现过高的内存占用。
或者,如果数据量太大,无法一次全部装入内存,你可以调用 stream 方法,以流式模式处理数据。这样,响应中的每个 chunk 都会被转换为一个相对较小的行数组 (该数组的大小取决于客户端从服务端接收到的特定 chunk 的大小——这可能会变化——以及单行的大小) ,并逐个 chunk 进行处理。
请参阅支持的数据格式列表,以确定哪种格式最适合你的流式场景。例如,如果你想流式传输 JSON 对象,可以选择 JSONEachRow,这样每一行都会被解析为一个 JS 对象;或者,也可以选择更紧凑的 JSONCompactColumns 格式,这样每一行都会成为一个紧凑的值数组。另请参见:streaming files。
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 方法
{ query_id: '...', executed: false }。在这种情况下,如果没有在方法参数 params 中提供 query_id,那么结果中的它将是空字符串,因为返回由客户端生成的随机 UUID 可能会造成混淆——毕竟,带有该 query_id 的查询并不存在于 system.query_log 表中。
如果 insert 语句已发送到服务器,则 executed 将为 true。
Node.js 中的 Insert 方法 与流式传输
insert 方法指定的数据格式,它既可以接受 Stream.Readable,也可以接受普通的 Array<T>。另请参阅关于文件流式传输的这一节。
通常应使用 await 等待 Insert 方法;不过,也可以先指定一个输入流,等到流完成后再等待 insert 操作 (这也会使 insert promise resolve) 。这在事件监听器及类似场景中可能很有用,但错误处理并不简单,而且客户端会有很多边界情况需要处理。作为替代方案,建议考虑使用异步插入,如此示例所示。
Web 版本限制
@clickhouse/client-web 中的插入操作仅支持 Array<T> 和 JSON* 格式。
由于浏览器兼容性欠佳,Web 版本目前尚不支持流式插入。
因此,Web 版本的 InsertParams 接口与 Node.js 版本略有不同,
因为 values 仅限使用 ReadonlyArray<T> 类型:
命令方法
FORMAT 子句不适用的情况,或者你根本不关心响应内容的情况。这类语句的一个示例是 CREATE TABLE 或 ALTER TABLE。
应使用 await 等待。
响应流会立即销毁,这意味着底层套接字会被释放。
Exec 方法
query/insert 的自定义查询,
并且需要获取返回结果,可以使用 exec 来替代 command。
exec 会返回一个可读流,必须在应用程序端消费或销毁。
Ping
ping 方法会在服务器可达时返回 true。
如果服务器不可达,结果中也会包含底层错误。
/ping 端点,而 Web 版本则使用简单的 SELECT 1 查询来达到类似效果,因为 /ping 端点不支持 CORS。
示例: (Node.js/Web) 对 ClickHouse 服务器实例执行一次简单的 ping。注意:对于 Web 版本,捕获到的错误会有所不同。
源代码。
ping 方法时一并检查凭据,或指定额外参数 (如 query_id) ,可以按如下方式使用:
ping 方法允许使用大多数标准 query 方法参数——请参见 PingParamsWithSelectQuery 类型定义。
Close (仅限 Node.js)
文件流式传输 (仅限 Node.js)
query 调用中使用的格式 (JSONEachRow、CSV 等) 以及输出文件名。
支持的数据格式
format 指定为 JSON 格式家族中的某一种 (JSONEachRow、JSONCompactEachRow 等) ,客户端会在传输过程中对数据进行序列化和反序列化。
以“原始”文本格式 (CSV、TabSeparated 和 CustomSeparated 家族) 提供的数据会在传输过程中直接发送,不做额外转换。
对于 Parquet,
selects 的主要用例很可能是将结果流写入文件。请参见客户端代码仓库中的示例。
JSONEachRowWithProgress 是一种仅用于输出的格式,支持在流中报告进度。更多详情请参见此示例。
ClickHouse 完整的输入和输出格式列表可在
此处查看。
支持的 ClickHouse 数据类型
对应的 JS 类型适用于所有
JSON* 格式,但将所有内容都表示为字符串的格式除外 (例如 JSONStringEachRow) 。
完整的受支持 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 转换为 String:
整数类型:Int64、Int128、Int256、UInt64、UInt128、UInt256
JSON* 家族的输出格式中,为避免整数溢出,它会以字符串形式返回,
因为这些类型的最大值大于 Number.MAX_SAFE_INTEGER。
不过,可以通过
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- 非致命错误;失败的ping请求会记录为 warning,因为底层错误已包含在返回结果中ERROR-query/insert/exec/command方法中的致命错误,例如请求失败
TLS 证书 (仅限 Node.js)
certs 文件夹中,
且 CA 文件名为 CA.pem:
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 在23.11 之前的 ClickHouse 版本中甚至可能低至 3 秒,且无需修改 config.xml。
你可以运行以下命令,从服务端响应请求头中找到正确的 Keep-Alive 超时值:
Connection 和 Keep-Alive 请求头的值。例如:
keep_alive_timeout 为 10 秒,你可以尝试将 keep_alive.idle_socket_ttl 提高到 9000 甚至 9500 毫秒,让空闲套接字保持打开状态的时间比默认情况下稍长一些。请留意可能出现的 “Socket hang-up” 错误,这表明服务端会先于客户端关闭连接;请逐步调低该值,直到错误消失。
故障排查
socket hang up 错误,可以通过以下几种方式解决:
-
启用至少为
WARN的日志级别 (默认值) 。这样可以检查应用程序代码中是否存在未消费或悬空的流:传输层会以 WARN 级别记录这类情况,因为它们可能导致套接字被 server 关闭。你可以按如下方式在 client 配置中启用日志: -
确保所需配置已应用到正确的 client instance。如果你的应用中有多个 client instance,请再次确认你实际用于 queries 的那个实例设置了正确的
keep_alive.idle_socket_ttl值。 -
在 client 配置中将
keep_alive.idle_socket_ttl调小 500 毫秒。在某些情况下,例如 client 与 server 之间网络延迟较高时,这样做可能会有帮助,可以排除这样一种情况:发出的 request 恰好拿到了一个即将被 server 关闭的套接字。 -
如果此错误发生在长时间运行且没有数据进出 (例如长时间运行的
INSERT FROM SELECT) 的 queries 期间,原因可能是 load balancer 或其他网络组件关闭了长连接或长时间运行的 requests。你可以尝试组合使用以下 ClickHouse 设置,在长时间运行的 queries 期间强制产生一些传入数据:不过请注意,在较新的 Node.js 版本中,接收到的请求头总大小限制为 16KB;在接收到一定数量的进度请求头后 (根据我们的测试,大约是 70-80 个) ,会抛出异常。 也可以采用一种完全不同的方法,彻底避免线上传输中的等待时间;这可以利用 HTTP interface 的一个“特性”:连接丢失时,变更 不会被取消。更多详情请参见这个示例 (第 2 部分) 。 -
也可以完全禁用 Keep-Alive 功能。在这种情况下,client 还会为每个 request 添加
Connection: close请求头,底层 HTTP agent 也不会复用连接。keep_alive.idle_socket_ttl设置将被忽略,因为不会有空闲套接字。这会带来额外开销,因为每个 request 都需要建立一个新连接。 -
可以运行一个简单的命令行测试,排除网络技术栈其他部分 (包括 Node.js 本身) 的潜在问题。测试时使用同一个 ClickHouse instance 和相同的网络路径 (即同一台机器或同一网段,例如某个 Kubernetes pod) ,例如使用
curl:你可能需要将其循环运行几分钟。如果你在curl中也看到类似错误,那么问题很可能与 client 配置无关,而是出在网络技术栈或 server configuration 上。 -
如果要使用原生 Node.js 功能测试连接,你可以尝试使用内置的
fetchAPI 向 ClickHouse server 发起一个简单的 HTTP request:
-
在某些情况下,应用程序代码或框架适配器可能会在实际执行查询前先发起一次
ping()。这可能会导致这样一种情况:ping()请求成功,但紧随其后的查询请求却因空闲连接的同一底层问题而失败,并报出 “socket hang up” 错误。如果你在日志中看到这种模式,请检查你的框架或应用程序代码中是否提供了禁用预先ping()的选项。这也有助于降低被中间网络组件限流的概率。 - 确保应用程序本身获得了足够的 CPU 时间,并且网络未被托管提供商限流。各种监控手段 (如 GC 暂停指标、事件循环延迟指标等) 也有助于排查潜在的资源饥饿问题。
- 尝试在启用 no-floating-promises ESLint 规则的情况下检查应用程序代码,这有助于识别未处理的 Promise,因为它们可能导致悬空的流和套接字。
只读用户
enable_http_compression 设置。以下配置会导致错误:
带路径名的代理
http://proxy:8123/clickhouse_server,请将 clickhouse_server 指定为 pathname 配置选项 (可以带前导斜杠,也可以不带) ;否则,如果直接在 url 中提供,它会被视为 database 选项。支持多段路径,例如 /my_proxy/db。
使用身份验证的反向代理
http_headers 设置在其中提供所需的请求头:
自定义 HTTP/HTTPS agent (Experimental,仅限 Node.js)
max_open_connections、keep_alive.enabled、tls) 来配置底层 HTTP 或 HTTPS agent,并由其处理与 ClickHouse server 的连接。此外,如果使用了 TLS 证书,底层 agent 还会配置所需的证书,并强制使用正确的 TLS 认证请求头。
从 1.2.0 版本开始,可以为客户端提供自定义 HTTP 或 HTTPS agent,以替换默认的底层 agent。这在网络配置较为复杂时可能会很有用。如果提供了自定义 agent,则适用以下条件:
max_open_connections和tls选项将_不起作用_,并会被客户端忽略,因为它们属于底层 agent 配置的一部分。keep_alive.enabled只会控制Connection请求头的默认值 (true->Connection: keep-alive,false->Connection: close) 。- 虽然空闲 keep-alive 套接字管理仍然会继续生效 (因为它不依赖于 agent,而是依赖于具体的套接字本身) ,但现在可以通过将
keep_alive.idle_socket_ttl的值设置为0来完全禁用它。
自定义代理的用法示例
set_basic_auth_header 设置禁用默认的授权请求头 (于 1.2.0 引入) ,因为它会与 TLS 请求头发生冲突。所有 TLS 请求头都应手动提供。
已知限制 (Node.js/web)
- 结果集暂无数据映射器,因此仅使用语言的基本类型。计划在支持 RowBinary format 后引入部分数据类型映射器。
- 某些 Decimal* 和 Date* / DateTime* 数据类型有一些注意事项。
- 使用 JSON* 家族格式时,大于 Int32 的数字会以字符串表示,因为 Int64+ 类型的最大值超过了
Number.MAX_SAFE_INTEGER。更多详情请参见 整数类型 部分。
已知限制 (Web)
select查询支持流式处理,但对插入操作不支持 (在类型层面也是如此) 。- 请求压缩已禁用,相关配置会被忽略。响应压缩可正常工作。
- 暂不支持日志。
性能优化提示
- 为减少应用程序的内存占用,在适用的情况下,可考虑对大型插入 (例如从文件进行插入) 以及 select 查询使用流。对于事件监听器和类似用例,异步插入 也是一个不错的选择,它可以尽量减少,甚至完全避免在客户端进行批处理。异步插入示例可在客户端代码仓库中找到,文件名前缀为
async_insert_。 - 该 client 默认不启用请求或响应压缩。不过,在查询或插入大型数据集时,你可以考虑通过
ClickHouseClientConfigOptions.compression启用压缩 (仅针对request或response,或同时启用两者) 。 - 压缩会带来明显的性能开销。对
request或response启用压缩,分别会降低插入或查询的速度,但会减少应用程序传输的网络流量。
联系我们
#clickhouse-js 频道) 或在 GitHub issues 中联系我们。