跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

Golang怎么操作ClickHouse_Golang ClickHouse教程【详解】

ClickHouse连接与操作问题多源于clickhouse-go/v2配置不当:端口错用(8123 HTTP vs 9000 TCP)、TLS未显式关闭、压缩不匹配;INSERT应批量用PrepareBatch+Send;ScanStruct依赖精确ch标签;空结果需检查rows.Err()。 连不上不是网络问题,八成是协议或参数错位;单条 INSERT 写百万行,性能差十倍不止;ScanStruct 字段不赋值却不报错——这些都不是 ClickHouse 本身的问题,而是 clickhouse-go/v2 的行为惯性在坑人。 clickhouse.Open 连接失败的三个高频原因 驱动默认走 TCP 协议 + TLS + LZ4 压缩,但本地开发环境往往只开了裸 TCP(9000 端口)且没配证书。你看到的
context deadline exceeded
或静默卡住,基本都出在这儿。
Addr
写成
"localhost:8123"
:这是 HTTP 端口,v2 默认走 TCP,得改成
"localhost:9000"
没关 TLS:
secure=false
必须显式加在 DSN 或 Options 里,否则握手失败,日志里不提示 TLS 相关错误,只超时 压缩不匹配:服务端没开 LZ4(查
SELECT * FROM system.settings WHERE name LIKE '%compression%'
),但客户端用了
clickhouse.Compression(clickhouse.CompressionLZ4)
,会报
Code: 287. DB::Exception: Unknown compression method
INSERT 性能差?别用 stmt.Exec 循环插 ClickHouse 不是关系型数据库,单行 INSERT 触发的是小块写入+ minor merge,完全违背列式存储的设计前提。10 万行用循环
stmt.Exec()
可能要几十秒;换成真批量,通常压到 1 秒内。 必须用
conn.PrepareBatch()
获取
Batch
对象,不是
conn.Prepare()
batch.Append()
只是攒数据,不发包;必须调
batch.Send()
才真正提交 每批控制在 1w–10w 行之间:太小吞吐上不去,太大易触发服务端
max_insert_block_size
限制或 OOM 别传 struct 实例:
batch.Append(row)
会 panic,必须按列拆成
[]int64
、
[]string
等切片分别 append rows.ScanStruct 字段不赋值却没报错 v2 的
ScanStruct
完全依赖结构体字段上的
ch:
标签,且大小写、拼写必须和 ClickHouse 列名严格一致。漏标、标错、大小写不匹配,它就跳过该字段——不 panic,不 warn,只给零值。 立即学习 “ go语言免费学习笔记(深入) ”; 结构体字段必须带
ch:"column_name"
,例如
Ts time.Time `ch:"event_time"`
ClickHouse 列是
user_id
,结构体里写成
UserID
却没标
ch:"user_id"
,那
UserID
就永远是 0
ScanStruct
不认
json:
标签,也完全忽略
db:
或
sql:
如果表字段含
Nullable(String)
,字段类型不能是
*string
,得用
sql.NullString
或
ch.String
(后者更贴合语义) Query 返回空结果但 rows.Err() 是 nil 这是最隐蔽的“假成功”:SQL 执行了,没报错,rows.Next() 返回 false,你以为没数据,其实是扫描中途出错被吞了。 必须在
for rows.Next()
循环结束后,立刻检查
if err := rows.Err(); err != nil
,很多“空结果”其实是这里出的错 别用
SELECT *
:字段顺序、别名、聚合函数会让
Scan()
地址传参错位,优先显式写出字段名,并严格按顺序传
&id, &name, &ts
时间类型注意时区:
DateTime
默认是 UTC,而
time.Now()
是本地时区,WHERE 条件比较前先统一用
.UTC()
或
.In(loc)
字符串字段含 NULL?用
*string
会 panic,得用
sql.NullString
或
ch.String
真正的难点不在语法,而在协议细节与类型对齐:TCP 端口和 HTTP 端口不能混,TLS 和压缩开关必须和服务端配置咬合,字段标签一个字母都不能错,NULL 和非 NULL 类型不能靠猜——这些地方一松懈,程序就静默失效。

相关文章