Copyright © 2022-2024 aizws.net · 网站版本: v1.2.6·内部版本: v1.23.3·
页面加载耗时 0.00 毫秒·物理内存 53.9MB ·虚拟内存 1299.5MB
欢迎来到 AI 中文社区(简称 AI 中文社),这里是学习交流 AI 人工智能技术的中文社区。 为了更好的体验,本站推荐使用 Chrome 浏览器。
Go 领域里,原生 SQL、SQLX、GORM 性能相差多少呢?几天打算测试比较它们的性能。AI 中文社网站数据库操作类库是我封装了 jmoiron/sqlx 的一个类,在开发过程中,发现这个库比原生的 database/sql 操作方便一些,起码填充数据结构的时候,省了很多代码,介于原生与 ORM 之间,但是远远达不到 ORM 这么方便,很多动态参数,掺杂了数据库字段在里面,如果日后修改数据库后,很容易出错,心里痒痒的,想用回 ORM ,这样代码优雅些,让代码健壮一些。
所以拿 database/sql,jmoiron/sqlx,gorm.io/gorm 三个库进行了性能测试,看看相差多少,从性能和健壮性上权衡,再决定下一步怎么选择,测试环境 MacBook Pro (Retina, 13-inch, Early 2015) ,2.7 GHz Intel Core i5 ,固态磁盘 256G, 内存 8 GB 1867 MHz DDR3,,数据库 PostgreSQL15。
测试结果如下:
看到最终的测试结果,发现 grom 的性能相对于原生的 database/sql 低了 6% - 50% 左右,特别并发量增加上去后越明显,而 jmoiron/sqlx 性能很接近原生的 database/sql ,并发量上次之后 3%-18% 的损耗,中低并发量的时候和原生性能不分仲伯,日常情况下,估计整体表现非常优异。这次测试,让我犹豫要不要切换 grom 了,反复测试了多次,测试结果稳定,代码发出来,大家看看有没有不公平的地方,我再检验。
package main
import (
"database/sql"
"fmt"
"testing"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
// go test -bench=. -benchmem -run=none
var (
dsn = "postgres://postgres:123456@localhost:5432/demo?sslmode=disable"
)
type Person struct {
Id int `db:"id"`
FirstName string `db:"first_name"`
LastName string `db:"last_name"`
Email string `db:"email"`
}
func (p Person) TableName() string {
return "person"
}
func Benchmark(b *testing.B) {
limits := []int{
10,
100,
1000,
10000,
}
// 原生 database/sql 连接池
sqlDB, _ := sql.Open("postgres", dsn)
sqlDB.SetMaxOpenConns(500)
sqlDB.SetMaxIdleConns(100)
// jmoiron/sqlx 连接池
sqlxDB, _ := sqlx.Connect("postgres", dsn)
sqlxDB.SetMaxOpenConns(500)
sqlxDB.SetMaxIdleConns(100)
// gorm.io/gorm
gormDB, _ := gorm.Open(postgres.Open(dsn), &gorm.Config{
SkipDefaultTransaction: true,
PrepareStmt: true,
DisableAutomaticPing: true,
})
db, _ := gormDB.DB()
db.SetMaxOpenConns(500)
db.SetMaxIdleConns(100)
for _, lim := range limits {
// Benchmark database/sql
b.Run(fmt.Sprintf("database/sql limit:%d", lim), func(b *testing.B) {
var res []Person
stmt, _ := sqlDB.Prepare("SELECT id,first_name,last_name,email FROM person LIMIT $1")
for i := 0; i < b.N; i++ {
rows, err := stmt.Query(lim)
if err != nil {
b.Fatal(err)
}
defer rows.Close()
for rows.Next() {
p := Person{}
rows.Scan(&p.Id, &p.FirstName, &p.LastName, &p.Email)
res = append(res, p)
}
}
})
// Benchmark jmoiron/sqlx
b.Run(fmt.Sprintf("jmoiron/sqlx limit:%d", lim), func(b *testing.B) {
stmt, _ := sqlxDB.Preparex("SELECT id,first_name,last_name,email FROM person LIMIT $1")
for i := 0; i < b.N; i++ {
var res []Person
err := stmt.Select(&res, lim)
if err != nil {
b.Fatal(err)
}
}
})
// Benchmark gorm.io/gorm
b.Run(fmt.Sprintf("gorm.io/gorm limit:%d", lim), func(b *testing.B) {
for i := 0; i < b.N; i++ {
var res []Person
err := gormDB.Limit(lim).Find(&res).Error
if err != nil {
b.Fatal(err)
}
}
})
fmt.Println("#######################################")
}
}