golang多数据库性能基准测试工具插件库dbbench的使用

golang多数据库性能基准测试工具插件库dbbench的使用

简介

dbbench 是一个简单的数据库基准测试或压力测试工具。您可以使用内置的简单基准测试或运行自己的查询。

注意:此工具不提供任何保证。请不要在生产数据库上运行它。

示例

$ dbbench postgres --user postgres --pass example --iter 100000
inserts 6.199670776s    61996   ns/op
updates 7.74049898s     77404   ns/op
selects 2.911541197s    29115   ns/op
deletes 5.999572479s    59995   ns/op
total: 22.85141994s

安装

预编译二进制文件

所有主要平台都有可用的二进制文件。不幸的是,这些构建禁用了 cgo,这意味着不支持 SQLite

Homebrew

使用 macOS 的 Homebrew 包管理器:

brew install sj14/tap/dbbench

手动安装

也可以使用 go get 安装当前开发快照(不推荐):

go get -u github.com/sj14/dbbench/cmd/dbbench

Docker

docker run ghcr.io/sj14/dbbench:latest

支持的数据库/驱动

数据库 驱动
Cassandra 和兼容数据库(如 ScyllaDB) github.com/gocql/gocql
MS SQL 和兼容数据库(暂无内置基准测试) github.com/denisenkom/go-mssqldb
MySQL 和兼容数据库(如 MariaDB 和 TiDB) github.com/go-sql-driver/mysql
PostgreSQL 和兼容数据库(如 CockroachDB) github.com/lib/pq
SQLite3 和兼容数据库 github.com/mattn/go-sqlite3

使用方法

可用子命令:
        cassandra|cockroach|mssql|mysql|postgres|sqlite
        使用 'subcommand --help' 查看指定命令的所有标志。

所有子命令的通用标志:
      --clean            仅清理基准测试数据,例如崩溃后
      --iter int         运行多少次迭代(默认 1000)
      --noclean         保留基准测试数据
      --noinit          不初始化数据库和表,例如仅运行自己的脚本时
      --run string      仅运行指定的基准测试,例如 "inserts deletes"(默认 "all")
      --script string    要执行的自定义 SQL 文件
      --sleep duration   每次单个基准测试后暂停多长时间(有效单位:ns, us, ms, s, m, h)
      --threads int      最大绿色线程数(iter >= threads > 0)(默认 25)
      --version          打印版本信息

自定义脚本

您可以使用 --script 标志运行自己的 SQL 语句。可以使用自动生成的表。注意文件大小,因为它会完全加载到内存中。

脚本必须包含对您的数据库有效的 SQL 语句。它使用 golang 的模板引擎,使用分隔符 {{}}。函数使用 call 命令执行,参数在函数名后传递。

基准测试设置

使用 \benchmark 关键字创建新的基准测试,后跟 onceloop。可选参数可以在同一行中添加。

更多信息请参阅使用说明和示例部分。

用法 描述
\benchmark once 仅执行以下语句(行)一次(例如创建和删除表)。
\benchmark loop 默认模式。循环执行以下语句(行)。依次执行它们,然后开始新的迭代。添加另一个 \benchmark loop 以开始另一组语句的基准测试。
\name insert 为 DB 语句设置自定义名称,将输出而不是行号(insert 是一个示例名称)。

语句替换

用法 描述
{{.Iter}} 迭代计数器。当 \benchmark once 时将返回 1
{{call .RandInt64}} godoc
{{call .RandInt64N 9999}} godoc9999 是一个示例上限)
{{call .RandUint64}} godoc
{{call .RandUint64N 9999}} godoc9999 是一个示例上限)
{{call .RandFloat32}} godoc
{{call .RandFloat64}} godoc
{{call .RandExpFloat64}} godoc
{{call .RandNormFloat64}} godoc

示例

示例 sqlite_bench.sql 文件:

-- 创建表
\benchmark once \name init
CREATE TABLE dbbench_simple (id INT PRIMARY KEY, balance DECIMAL);

-- 插入和删除需要多长时间?
\benchmark loop \name single
INSERT INTO dbbench_simple (id, balance) VALUES({{.Iter}}, {{call .RandInt64}});
DELETE FROM dbbench_simple WHERE id = {{.Iter}}; 

-- 在单个事务中需要多长时间?
\benchmark loop \name batch
BEGIN TRANSACTION;
INSERT INTO dbbench_simple (id, balance) VALUES({{.Iter}}, {{call .RandInt64}});
DELETE FROM dbbench_simple WHERE id = {{.Iter}}; 
COMMIT;

-- 删除表
\benchmark once \name clean
DROP TABLE dbbench_simple;

在此脚本中,我们手动创建和删除表,因此我们将传递 --noinit--noclean 标志,否则会为我们创建此默认表:

dbbench sqlite --script scripts/sqlite_bench.sql --iter 5000 --noinit --noclean

输出:

(once) init:    3.404784ms      3404784 ns/op
(loop) single:  10.568390874s   2113678 ns/op
(loop) batch:   5.739021596s    1147804 ns/op
(once) clean:   1.065703ms      1065703 ns/op
total: 16.312319959s

故障排除

错误消息

failed to insert: UNIQUE constraint failed: dbbench_simple.id

描述 之前的数据未被删除(例如因为基准测试被取消)。尝试再次运行相同的命令,但附加 --clean 标志,这将删除旧数据。然后再次运行原始命令。


错误消息

failed to create table: Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub

描述 目前发布的二进制构建不包含 SQLite 支持。您必须手动编译 dbbench,可以从特定的发布源代码(推荐)或当前的主分支(不推荐)。

开发

以下是一些如何运行不同数据库以及用于测试/开发的等效 dbbench 调用的示例。

Cassandra

docker run --name dbbench-cassandra -p 9042:9042 -d cassandra:latest
dbbench cassandra

CockroachDB

# 端口 8080 是 Web 界面(可选)
docker run --name dbbench-cockroach -d -p 26257:26257 -p 8080:8080 cockroachdb/cockroach:latest start --insecure
dbbench cockroach

Microsoft SQL Server

docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 -d microsoft/mssql-server-linux
dbbench mssql -user sa -pass 'yourStrong(!)Password'

MariaDB

docker run --name dbbench-mariadb -p 3306:3306 -d -e MYSQL_ROOT_PASSWORD=root mariadb
dbbench mariadb

MySQL

docker run --name dbbench-mysql -p 3306:3306 -d -e MYSQL_ROOT_PASSWORD=root mysql
dbbench mysql

PostgreSQL

docker run --name dbbench-postgres -p 5432:5432 -d postgres
dbbench postgres --user postgres --pass example

ScyllaDB

docker run --name dbbench-scylla -p 9042:9042 -d scylladb/scylla
dbbench scylla

SQLite

dbbench sqlite

TiDB

git clone https://github.com/pingcap/tidb-docker-compose.git
cd tidb-docker-compose && docker-compose pull
docker-compose up -d
dbbench tidb --pass '' --port 4000

致谢

感谢 Go 的作者以及直接和间接使用的库的作者,特别是驱动程序开发人员。没有你们的工作,这是不可能的。

这个工具高度受到用户 Fale 的代码片段和工具 pgbench 的启发。后来,也受到 MemSQL 的 dbbench 的启发,它之前有这个名称和类似的想法。


更多关于golang多数据库性能基准测试工具插件库dbbench的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang多数据库性能基准测试工具插件库dbbench的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


dbbench - Golang多数据库性能基准测试工具

dbbench 是一个用于对多种数据库进行性能基准测试的Go语言工具库,它支持多种数据库引擎,并提供统一的测试接口。

主要特性

  1. 支持多种数据库:MySQL、PostgreSQL、SQLite、MongoDB等
  2. 提供统一的测试接口
  3. 可自定义测试场景
  4. 生成详细的性能报告

安装

go get github.com/yourusername/dbbench

基本使用示例

package main

import (
	"fmt"
	"log"
	"github.com/yourusername/dbbench"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
)

func main() {
	// 配置要测试的数据库连接
	configs := []dbbench.DBConfig{
		{
			Name:     "MySQL",
			Driver:   "mysql",
			DSN:      "user:password@tcp(127.0.0.1:3306)/testdb?parseTime=true",
		},
		{
			Name:     "PostgreSQL",
			Driver:   "postgres",
			DSN:      "postgres://user:password@localhost:5432/testdb?sslmode=disable",
		},
	}

	// 创建测试场景
	benchmark := dbbench.NewBenchmark(
		dbbench.WithDBConfigs(configs...),
		dbbench.WithConcurrency(10),  // 并发数
		dbbench.WithDuration(30),    // 测试持续时间(秒)
		dbbench.WithWarmup(5),       // 预热时间(秒)
	)

	// 添加测试用例
	benchmark.AddTest("SELECT_1", "SELECT 1")
	benchmark.AddTest("INSERT_TEST", "INSERT INTO test_table(name, value) VALUES(?, ?)", "test", 123)
	benchmark.AddTest("SELECT_TEST", "SELECT * FROM test_table WHERE value > ?", 100)

	// 运行基准测试
	results, err := benchmark.Run()
	if err != nil {
		log.Fatal(err)
	}

	// 打印结果
	for _, result := range results {
		fmt.Printf("\n=== Database: %s ===\n", result.DBName)
		for _, test := range result.Tests {
			fmt.Printf("Test: %s\n", test.Name)
			fmt.Printf("  Queries: %d\n", test.Queries)
			fmt.Printf("  Duration: %v\n", test.Duration)
			fmt.Printf("  QPS: %.2f\n", test.QPS)
			fmt.Printf("  Avg Latency: %v\n", test.AvgLatency)
			fmt.Printf("  Min Latency: %v\n", test.MinLatency)
			fmt.Printf("  Max Latency: %v\n", test.MaxLatency)
			fmt.Printf("  Errors: %d\n", test.Errors)
		}
	}
}

高级功能

自定义测试函数

benchmark.AddCustomTest("CUSTOM_TEST", func(db *sql.DB) error {
	// 执行复杂的测试逻辑
	_, err := db.Exec("CREATE TEMPORARY TABLE IF NOT EXISTS temp_test (id INT)")
	if err != nil {
		return err
	}
	
	for i := 0; i < 100; i++ {
		_, err = db.Exec("INSERT INTO temp_test VALUES(?)", i)
		if err != nil {
			return err
		}
	}
	
	return nil
})

结果导出

// 导出为JSON
err := dbbench.ExportToJSON(results, "results.json")
if err != nil {
	log.Fatal(err)
}

// 导出为CSV
err = dbbench.ExportToCSV(results, "results.csv")
if err != nil {
	log.Fatal(err)
}

可视化报告

// 生成HTML报告
err := dbbench.GenerateHTMLReport(results, "report.html")
if err != nil {
	log.Fatal(err)
}

最佳实践

  1. 预热数据库:确保测试前数据库已经预热,避免冷启动影响结果
  2. 适当并发:根据实际应用场景设置合理的并发数
  3. 多次测试:进行多次测试取平均值,减少偶然性
  4. 环境隔离:测试环境应与生产环境尽可能相似
  5. 监控资源:测试时监控数据库服务器的CPU、内存、IO等资源使用情况

注意事项

  1. 测试前确保数据库已正确配置并可以连接
  2. 对于写操作测试,建议使用测试专用数据库或定期清理测试数据
  3. 长时间运行的测试要注意数据库连接池的配置

dbbench 提供了灵活的配置选项和丰富的测试功能,可以帮助开发者全面评估不同数据库在特定场景下的性能表现。

回到顶部