Skip to content

Go

GreptimeDB 使用不同的客户端库来写入和查询数据。 你根据需求可以选择合适的客户端库。

写入数据

GreptimeDB 提供了一个 ingester 库来帮助你写入数据。 它使用 gRPC 协议,支持自动生成表结构,无需在写入数据前创建表。 更多信息请参考 自动生成表结构

GreptimeDB 提供的 Go Ingest SDK 是一个轻量级、并发安全的库,使用起来非常简单。

安装

使用下方的命令安装 Go Ingest SDK:

shell
go get -u github.com/GreptimeTeam/greptimedb-ingester-go
go get -u github.com/GreptimeTeam/greptimedb-ingester-go

引入到代码中:

go
import (
    greptime "github.com/GreptimeTeam/greptimedb-ingester-go"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table/types"
)
import (
    greptime "github.com/GreptimeTeam/greptimedb-ingester-go"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table"
    "github.com/GreptimeTeam/greptimedb-ingester-go/table/types"
)

连接数据库

连接 GreptimeDB 时,通常需要用户名和密码。 关于如何设置 GreptimeDB 的鉴权方式,请参考鉴权。 这里我们在使用 ingester 库连接 GreptimeDB 时设置用户名和密码。

go
cfg := greptime.NewConfig("127.0.0.1").
    // 将数据库名称更改为你的数据库名称
    WithDatabase("public").
    // 默认端口 4001
    // WithPort(4001).
    // 如果服务配置了 TLS ,设置 TLS 选项来启用安全连接
    // WithInsecure(false).
    // 设置鉴权信息
    WithAuth("username", "password")

cli, _ := greptime.NewClient(cfg)
cfg := greptime.NewConfig("127.0.0.1").
    // 将数据库名称更改为你的数据库名称
    WithDatabase("public").
    // 默认端口 4001
    // WithPort(4001).
    // 如果服务配置了 TLS ,设置 TLS 选项来启用安全连接
    // WithInsecure(false).
    // 设置鉴权信息
    WithAuth("username", "password")

cli, _ := greptime.NewClient(cfg)

数据模型

表中的每条行数据包含三种类型的列:TagTimestampField。更多信息请参考 数据模型。 列值的类型可以是 StringFloatIntTimestamp 等。更多信息请参考 数据类型

低层级 API

GreptimeDB 的低层级 API 通过向具有预定义模式的 table 对象添加 row 来写入数据。

创建行数据

以下代码片段首先构建了一个名为 cpu_metric 的表,其中包括 hostcpu_usercpu_systs 列。 随后,它向表中插入了一行数据。

该表包含三种类型的列:

  • Taghost 列,值类型为 String
  • Fieldcpu_usercpu_sys 列,值类型为 Float
  • Timestampts 列,值类型为 Timestamp
go
// 为 CPU 指标构建表结构
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // 处理错误
}

// 添加一个 'Tag' 列,用于主机标识符
cpuMetric.AddTagColumn("host", types.STRING)
// 添加一个 'Timestamp' 列,用于记录数据收集的时间
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
// 添加 'Field' 列,用于测量用户和系统 CPU 使用率
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)

// 插入示例数据
// 注意:参数必须按照定义的表结构中的列的顺序排列:host, ts, cpu_user, cpu_sys
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.11, 0.13)
if err != nil {
    // 处理错误
}
// 为 CPU 指标构建表结构
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // 处理错误
}

// 添加一个 'Tag' 列,用于主机标识符
cpuMetric.AddTagColumn("host", types.STRING)
// 添加一个 'Timestamp' 列,用于记录数据收集的时间
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
// 添加 'Field' 列,用于测量用户和系统 CPU 使用率
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)

// 插入示例数据
// 注意:参数必须按照定义的表结构中的列的顺序排列:host, ts, cpu_user, cpu_sys
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.11, 0.13)
if err != nil {
    // 处理错误
}

为了提高写入数据的效率,你可以一次创建多行数据以便写入到 GreptimeDB。

go
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // 处理错误
}
cpuMetric.AddTagColumn("host", types.STRING)
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
if err != nil {
    // 处理错误
}

memMetric, err := table.New("mem_metric")
if err != nil {
    // 处理错误
}
memMetric.AddTagColumn("host", types.STRING)
memMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
memMetric.AddFieldColumn("mem_usage", types.FLOAT)
err = memMetric.AddRow("127.0.0.1", time.Now(), 112)
if err != nil {
    // 处理错误
}
cpuMetric, err := table.New("cpu_metric")
if err != nil {
    // 处理错误
}
cpuMetric.AddTagColumn("host", types.STRING)
cpuMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
cpuMetric.AddFieldColumn("cpu_user", types.FLOAT)
cpuMetric.AddFieldColumn("cpu_sys", types.FLOAT)
err = cpuMetric.AddRow("127.0.0.1", time.Now(), 0.1, 0.12)
if err != nil {
    // 处理错误
}

memMetric, err := table.New("mem_metric")
if err != nil {
    // 处理错误
}
memMetric.AddTagColumn("host", types.STRING)
memMetric.AddTimestampColumn("ts", types.TIMESTAMP_MILLISECOND)
memMetric.AddFieldColumn("mem_usage", types.FLOAT)
err = memMetric.AddRow("127.0.0.1", time.Now(), 112)
if err != nil {
    // 处理错误
}

插入数据

下方示例展示了如何向 GreptimeDB 的表中插入行数据。

go
resp, err := cli.Write(context.Background(), cpuMetric, memMetric)
if err != nil {
    // 处理错误
}
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())
resp, err := cli.Write(context.Background(), cpuMetric, memMetric)
if err != nil {
    // 处理错误
}
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())

流式插入

当你需要插入大量数据时,例如导入历史数据,流式插入是非常有用的。

go
err := cli.StreamWrite(context.Background(), cpuMetric, memMetric)
if err != nil {
    // 处理错误
}
err := cli.StreamWrite(context.Background(), cpuMetric, memMetric)
if err != nil {
    // 处理错误
}

在所有数据写入完毕后关闭流式写入。 一般情况下,连续写入数据时不需要关闭流式写入。

go
affected, err := cli.CloseStream(ctx)
affected, err := cli.CloseStream(ctx)

高层级 API

SDK 的高层级 API 使用 ORM 风格的对象写入数据, 它允许你以更面向对象的方式创建、插入和更新数据,为开发者提供了更友好的体验。 然而,高层级 API 不如低层级 API 高效。 这是因为 ORM 风格的对象在转换对象时可能会消耗更多的资源和时间。

创建行数据

go
type CpuMetric struct {
    Host            string    `greptime:"tag;column:host;type:string"`
    CpuUser         float64   `greptime:"field;column:cpu_user;type:float64"`
    CpuSys          float64   `greptime:"field;column:cpu_sys;type:float64"`
    Ts              time.Time `greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
}

func (CpuMetric) TableName() string {
	return "cpu_metric"
}

cpuMetrics := []CpuMetric{
    {
        Host:        "127.0.0.1",
        CpuUser:     0.10,
        CpuSys:      0.12,
        Ts:          time.Now(),
    }
}
type CpuMetric struct {
    Host            string    `greptime:"tag;column:host;type:string"`
    CpuUser         float64   `greptime:"field;column:cpu_user;type:float64"`
    CpuSys          float64   `greptime:"field;column:cpu_sys;type:float64"`
    Ts              time.Time `greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
}

func (CpuMetric) TableName() string {
	return "cpu_metric"
}

cpuMetrics := []CpuMetric{
    {
        Host:        "127.0.0.1",
        CpuUser:     0.10,
        CpuSys:      0.12,
        Ts:          time.Now(),
    }
}

插入数据

go
resp, err := cli.WriteObject(context.Background(), cpuMetrics)
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())
resp, err := cli.WriteObject(context.Background(), cpuMetrics)
log.Printf("affected rows: %d\n", resp.GetAffectedRows().GetValue())

流式插入

当你需要插入大量数据时,例如导入历史数据,流式插入是非常有用的。

go
err := streamClient.StreamWriteObject(context.Background(), cpuMetrics, memMetrics)
err := streamClient.StreamWriteObject(context.Background(), cpuMetrics, memMetrics)

在所有数据写入完毕后关闭流式写入。 一般情况下,连续写入数据时不需要关闭流式写入。

go
affected, err := cli.CloseStream(ctx)
affected, err := cli.CloseStream(ctx)

更多示例

有关更多可运行的代码片段和常用方法的解释,请参阅示例

Ingester 库参考

查询数据

GreptimeDB 使用 SQL 作为主要查询语言,兼容 MySQL 和 PostgreSQL。 因此,我们推荐使用成熟的 SQL 驱动来查询数据。

推荐的查询库

我们推荐使用 GORM 库来查询数据。

安装

使用下方的命令安装 GORM:

shell
go get -u gorm.io/gorm
go get -u gorm.io/gorm

以 MySQL 为例安装 driver:

shell
go get -u gorm.io/driver/mysql
go get -u gorm.io/driver/mysql

引入到代码中:

go
import (
    "gorm.io/gorm"
    "gorm.io/driver/mysql"
)
import (
    "gorm.io/gorm"
    "gorm.io/driver/mysql"
)

连接数据库

下方的例子展示了如何连接到 GreptimeDB:

go
type Mysql struct {
	Host     string
	Port     string
	User     string
	Password string
	Database string

	DB *gorm.DB
}

m := &Mysql{
    Host:     "127.0.0.1",
    Port:     "4002", // MySQL 协议的默认端口
    User:     "username",
    Password: "password",
    Database: "public",
}

dsn := fmt.Sprintf("tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
    m.Host, m.Port, m.Database)
dsn = fmt.Sprintf("%s:%s@%s", m.User, m.Password, dsn)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
    // 错误处理
}
m.DB = db
type Mysql struct {
	Host     string
	Port     string
	User     string
	Password string
	Database string

	DB *gorm.DB
}

m := &Mysql{
    Host:     "127.0.0.1",
    Port:     "4002", // MySQL 协议的默认端口
    User:     "username",
    Password: "password",
    Database: "public",
}

dsn := fmt.Sprintf("tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
    m.Host, m.Port, m.Database)
dsn = fmt.Sprintf("%s:%s@%s", m.User, m.Password, dsn)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
    // 错误处理
}
m.DB = db

Raw SQL

我们推荐使用 Raw SQL 来体验 GreptimeDB 的全部功能。 下面的例子展示了如何使用 Raw SQL 查询数据:

下方的代码声明了一个 GORM 对象模型:

go
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey"`
    Ts          time.Time `gorm:"column:ts;primaryKey"`
    CpuUser     float64   `gorm:"column:cpu_user"`
    CpuSys      float64   `gorm:"column:cpu_sys"`
}
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey"`
    Ts          time.Time `gorm:"column:ts;primaryKey"`
    CpuUser     float64   `gorm:"column:cpu_user"`
    CpuSys      float64   `gorm:"column:cpu_sys"`
}

如果你正在使用 ORM API 来插入数据,你可以在模型中同时声明 GORM 和 Greptime 标签。

go
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey" greptime:"tag;column:host;type:string"`
    Ts          time.Time `gorm:"column:ts;primaryKey"   greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
    CpuUser     float64   `gorm:"column:cpu_user"        greptime:"field;column:cpu_user;type:float64"`
    CpuSys      float64   `gorm:"column:cpu_sys"         greptime:"field;column:cpu_sys;type:float64"`
}
type CpuMetric struct {
    Host        string    `gorm:"column:host;primaryKey" greptime:"tag;column:host;type:string"`
    Ts          time.Time `gorm:"column:ts;primaryKey"   greptime:"timestamp;column:ts;type:timestamp;precision:millisecond"`
    CpuUser     float64   `gorm:"column:cpu_user"        greptime:"field;column:cpu_user;type:float64"`
    CpuSys      float64   `gorm:"column:cpu_sys"         greptime:"field;column:cpu_sys;type:float64"`
}

声明表名:

go
func (CpuMetric) TableName() string {
	return "cpu_metric"
}
func (CpuMetric) TableName() string {
	return "cpu_metric"
}

使用原始 SQL 查询数据:

go
var cpuMetric CpuMetric
db.Raw("SELECT * FROM cpu_metric LIMIT 10").Scan(&result)
var cpuMetric CpuMetric
db.Raw("SELECT * FROM cpu_metric LIMIT 10").Scan(&result)

查询库参考

有关如何使用查询库的更多信息,请参考相应库的文档:

GORM