Python clickhouse-connect 的 HTTP 接口实践

7次阅读

clickhouse http连接失败主因是端口错误(需用8123而非9000)、服务端未启用http_port或防火墙拦截;query()空结果或400错误多因sql末尾分号或参数未用parameters字典;大批量写入应优先用insert_df()或insert_json()并分批。

Python clickhouse-connect 的 HTTP 接口实践

clickhouse-connect 连不上 HTTP 接口?先看这三件事

连不上基本不是库的问题,而是服务端没开 HTTP 或客户端配错了端口/路径。ClickHouse 默认监听 tcp_port(9000),但 clickhouse-connect 走的是 HTTP 协议,必须用 http_port(默认 8123)——很多人卡在这儿。

  • 确认服务端 config.xml<http_port>8123</http_port> 已启用,且防火墙放行该端口
  • 客户端连接时不能写 host='localhost', port=9000,得显式指定 port=8123 或直接用 url='http://localhost:8123'
  • 如果 ClickHouse 开在 docker 里,注意宿主机网络模式:用 host 模式或映射 -p 8123:8123,别只映射了 9000

query() 返回空结果或报 HTTPError 400?检查 SQL 和参数格式

clickhouse-connectquery() 对 SQL 语法敏感,尤其不支持某些客户端习惯的写法。它底层发的是 HTTP POST 请求,SQL 是纯文本体,不走二进制协议解析。

  • 避免在 SQL 末尾加 ;——部分版本会触发 DB::Exception: Cannot parse input: expected end of stream
  • 传参要用 parameters 字典,别拼字符串client.query('select * FROM t WHERE id = {id:Int32}', parameters={'id': 123})
  • DDL 语句(如 CREATE table)能执行,但返回结果为空;想确认是否成功,得捕获异常或查 system.tables

大批量写入慢?别用 insert(),改用 insert_df() 或流式 insert_json()

insert() 是逐行转成 HTTP 表单提交,吞吐极低;而 insert_df() 会自动压缩 + 用 INSERT ... format Native 二进制协议(通过 HTTP 封装),快一个数量级。

  • pandas DataFrame 写入:确保列名和 ClickHouse 表字段严格一致,类型尽量匹配(datetime64[ns]DateTimeint64Int64
  • 原始数据是 JSON 数组?用 insert_json(data, 'table_name'),比手动构造 CSV 或 TSV 更稳
  • 单次插入超过 10 万行?拆成 5–10 万一批,避免 HTTP 超时或服务端内存溢出

遇到 ReadTimeoutConnectionResetError 怎么调参?

超时不是网络问题,大概率是 ClickHouse 服务端配置太保守,或客户端没设对。HTTP 连接在长查询、大结果集场景下很容易断。

立即学习Python免费学习笔记(深入)”;

  • 服务端要调 max_http_timeout_ms(默认 300000ms=5 分钟),写入场景建议设为 600000
  • 客户端初始化 client 时加参数:connect_timeout=30, query_timeout=600,这两个值必须 ≤ 服务端配置
  • 别忽略 compress=True(默认开启),对大结果集能明显降低传输时间,但服务端需开启 enable_http_compression

HTTP 接口的边界很清晰:它不支持事务、不支持 session 级变量、不保证语句顺序执行(尤其并发写)。如果你需要强一致性或复杂控制流,就得切回原生 TCP 协议或换用 clickhouse-driver

text=ZqhQzanResources