快速入门
让我们从一个简单的示例开始。这将连接到 ClickHouse,并从系统数据库中查询数据。开始之前,你需要准备好连接信息。
连接详情
要通过原生 TCP 连接到 ClickHouse,你需要以下信息:
| Parameters | Description |
|---|---|
HOST and PORT |
通常,使用 TLS 时端口为 9440;不使用 TLS 时端口为 9000。 |
DATABASE NAME |
默认会有一个名为 default 的数据库,请使用你要连接的数据库名称。 |
USERNAME and PASSWORD |
默认用户名为 default。请根据你的使用场景使用相应的用户名。 |
你的 ClickHouse Cloud 服务的详细信息可在 ClickHouse Cloud 控制台中查看。 选择要连接的服务,然后点击 Connect:

选择 Native,即可在示例 clickhouse-client 命令中看到详细信息。

如果你使用的是自管理 ClickHouse,连接详细信息由你的 ClickHouse 管理员设置。
初始化模块
mkdir clickhouse-golang-example
cd clickhouse-golang-example
go mod init clickhouse-golang-example复制示例代码
将这段代码复制到 clickhouse-golang-example 目录下,并保存为 main.go。
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
)
func main() {
conn, err := connect()
if err != nil {
panic(err)
}
ctx := context.Background()
rows, err := conn.Query(ctx, "SELECT name, toString(uuid) as uuid_str FROM system.tables LIMIT 5")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name, uuid string
if err := rows.Scan(&name, &uuid); err != nil {
log.Fatal(err)
}
log.Printf("name: %s, uuid: %s", name, uuid)
}
// 注意:不要跳过 rows.Err() 检查
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}
func connect() (driver.Conn, error) {
var (
ctx = context.Background()
conn, err = clickhouse.Open(&clickhouse.Options{
Addr: []string{"<CLICKHOUSE_SECURE_NATIVE_HOSTNAME>:9440"},
Auth: clickhouse.Auth{
Database: "default",
Username: "default",
Password: "<DEFAULT_USER_PASSWORD>",
},
ClientInfo: clickhouse.ClientInfo{
Products: []struct {
Name string
Version string
}{
{Name: "an-example-go-client", Version: "0.1"},
},
},
Debugf: func(format string, v ...interface{}) {
fmt.Printf(format, v)
},
TLS: &tls.Config{
InsecureSkipVerify: true,
},
})
)
if err != nil {
return nil, err
}
if err := conn.Ping(ctx); err != nil {
if exception, ok := err.(*clickhouse.Exception); ok {
fmt.Printf("Exception [%d] %s \n%s\n", exception.Code, exception.Message, exception.StackTrace)
}
return nil, err
}
return conn, nil
}执行 go mod tidy
go mod tidy设置连接信息
前面你已经查到了连接信息。请在 main.go 的 connect() 函数中进行设置:
func connect() (driver.Conn, error) {
var (
ctx = context.Background()
conn, err = clickhouse.Open(&clickhouse.Options{
Addr: []string{"<CLICKHOUSE_SECURE_NATIVE_HOSTNAME>:9440"},
Auth: clickhouse.Auth{
Database: "default",
Username: "default",
Password: "<DEFAULT_USER_PASSWORD>",
},运行示例
go run .2023/03/06 14:18:33 name: COLUMNS, uuid: 00000000-0000-0000-0000-000000000000
2023/03/06 14:18:33 name: SCHEMATA, uuid: 00000000-0000-0000-0000-000000000000
2023/03/06 14:18:33 name: TABLES, uuid: 00000000-0000-0000-0000-000000000000
2023/03/06 14:18:33 name: VIEWS, uuid: 00000000-0000-0000-0000-000000000000
2023/03/06 14:18:33 name: hourly_data, uuid: a4e36bd4-1e82-45b3-be77-74a0fe65c52b了解更多
本类别中的其余文档将详细介绍 ClickHouse Go 客户端。
概述
ClickHouse 支持两个官方 Go 客户端。这两个客户端相辅相成,并有意面向不同的使用场景。
- clickhouse-go - 高级语言客户端,支持 Go 标准
database/sql接口或原生 ClickHouse API。 - ch-go - 底层客户端。仅支持原生接口。
clickhouse-go 提供高级接口,允许用户以面向行的语义执行查询和插入,并支持对数据类型要求较宽松的批处理——只要不会造成潜在的精度损失,值就会自动转换。相比之下,ch-go 提供经过优化的面向列接口,可实现快速的数据块流式传输,同时保持较低的 CPU 和内存开销,但代价是类型限制更严格,使用也更复杂。
从 2.3 版本开始,clickhouse-go 使用 ch-go 处理编码、解码和压缩等底层功能。两个客户端都使用原生格式进行编码以获得最佳性能,并且都可以通过 ClickHouse 原生协议通信。在用户需要通过代理或负载均衡转发流量的场景下,clickhouse-go 还支持使用 HTTP 作为传输机制。
四种连接方式
clickhouse-go 提供两个相互独立的选择:使用哪种 API 和 使用哪种传输方式。两者组合后共有四种连接模式:
| TCP (原生协议,端口 9000/9440) | HTTP (端口 8123/8443) | |
|---|---|---|
ClickHouse API (clickhouse.Open) |
默认——性能最佳 | 设置 Protocol: clickhouse.HTTP |
database/sql API (OpenDB / sql.Open) |
clickhouse://host:9000 |
http://host:8123 |
选择 API: 如果你追求最高性能和完整功能集 (进度回调、列式插入、丰富的类型支持) ,请选择 ClickHouse API。如果需要与 ORM 或依赖标准 Go 数据库接口的工具集成,请选择 database/sql。
选择传输方式: TCP 更快,也是默认选项。当你的基础设施要求使用 HTTP 时,可切换到 HTTP——例如,需要通过 HTTP 负载均衡器或代理连接,或者需要 HTTP 特有功能时,如带临时表的会话,或额外的压缩算法 (gzip、deflate、br) 。
无论使用哪种传输方式,这两种 API 都使用原生二进制编码,因此 HTTP 不会带来额外的序列化开销。
| 原生格式 | TCP 传输 | HTTP 传输 | 批量写入 | 结构体编组 | 压缩 | 进度回调 | |
|---|---|---|---|---|---|---|---|
| ClickHouse API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
database/sql API |
✅ | ✅ | ✅ | ✅ | ✅ |
选择客户端
选择客户端库取决于你的使用模式以及对最佳性能的需求。对于插入密集型场景,即每秒需要执行数百万次插入时,我们建议使用底层客户端 ch-go。该客户端避免了将数据从面向行的格式转换为列格式所带来的额外开销,而 ClickHouse 原生格式正是如此要求的。此外,它还避免使用反射或 interface{} (any) 类型,从而简化了使用方式。
对于以聚合查询为主的工作负载,或者插入吞吐量较低的工作负载,clickhouse-go 提供了熟悉的 database/sql 接口以及更直观的行语义。你还可以选择使用 HTTP 作为传输协议,并借助辅助函数在行与结构体之间进行编组和反编组。
| 原生格式 | 原生协议 | HTTP 协议 | 面向行的 API | 面向列的 API | 类型灵活性 | 压缩 | 查询占位符 | |
|---|---|---|---|---|---|---|---|---|
| clickhouse-go | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| ch-go | ✅ | ✅ | ✅ | ✅ |
安装
该驱动的 v1 版本已弃用,今后不会再有功能更新,也不再支持新的 ClickHouse 数据类型。你应迁移到 v2,它具有更出色的性能。
要安装该客户端的 2.x 版本,请将该包添加到你的 go.mod 文件中:
require github.com/ClickHouse/clickhouse-go/v2 main
或者,克隆该仓库:
git clone --branch v2 https://github.com/clickhouse/clickhouse-go.git $GOPATH/src/github如需安装其他版本,请相应修改路径或分支名称。
mkdir my-clickhouse-app && cd my-clickhouse-app
cat > go.mod <<-END
module my-clickhouse-app
go 1.21
require github.com/ClickHouse/clickhouse-go/v2 main
END
cat > main.go <<-END
package main
import (
"fmt"
"github.com/ClickHouse/clickhouse-go/v2"
)
func main() {
conn, _ := clickhouse.Open(&clickhouse.Options{Addr: []string{"127.0.0.1:9000"}})
v, _ := conn.ServerVersion()
fmt.Println(v.String())
}
END
go mod tidy
go run main.go版本说明
该客户端独立于 ClickHouse 发布。2.x 表示当前正在开发的主版本。2.x 的所有版本都应彼此兼容。
ClickHouse 兼容性
该客户端支持:
- 此处列出的所有当前仍受支持的 ClickHouse 版本。一旦某个 ClickHouse 版本停止支持,也将不再针对客户端发行版对其进行主动测试。
- 客户端发布之日前后 2 年内的所有 ClickHouse 版本。请注意,只有 LTS 版本会被主动测试。
Golang 兼容性
| 客户端版本 | Golang 版本 |
|---|---|
| => 2.0 <= 2.2 | 1.17, 1.18 |
| >= 2.3, < 2.41 | 1.18+ |
| >= 2.41 | 1.21+ |
| >= 2.43 | 1.24+ |
最佳实践
- 尽可能使用 ClickHouse API,尤其是在处理基本类型时。这样可以避免大量的反射和间接调用。
- 如果要读取大型数据集,请考虑调整
BlockBufferSize。这会增加内存占用,但也意味着在迭代行时可以并行解码更多块。默认值 2 相对保守,可尽量减少内存开销。值越高,内存中保留的块就越多。这需要根据实际情况测试,因为不同查询产生的块大小可能不同。因此,也可以通过 Context 在查询级别进行设置。 - 写入数据时,请尽量明确指定类型。虽然客户端力求灵活,例如允许将字符串解析为 UUID 或 IP,但这需要进行数据校验,并会在写入时带来额外开销。
- 尽可能使用按列插入。同样,这类插入也应使用强类型,以避免客户端转换你的值。
- 遵循 ClickHouse 的建议,以获得最佳插入性能。
后续步骤
- 配置 — 连接设置、TLS、身份验证、日志、压缩
- ClickHouse API — 用于查询和插入操作的原生 Go API
- 数据库/SQL API — 标准
database/sql接口 - 数据类型 — Go 类型映射和复杂类型支持