Golang中的ORM框架评测及性能分析
ORM是对象关系映射(Object-Relational Mapping)的缩写,是一种通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中的技术。在Golang中,ORM框架也是非常重要的,因为它可以帮助我们简化数据库操作的复杂度,提高开发效率。本文将会对Golang中的ORM框架进行评测及性能分析,以便读者能够选择适合自己的ORM框架。
1. GORM
GORM是一个比较流行的Golang ORM框架,它提供了非常多的特性和工具,方便我们进行数据库操作。GORM支持MySQL、SQLite、PostgreSQL、SQL Server等多个数据库,并且允许我们定义模型结构体,对模型的增删改查都提供了非常友好的接口。
下面是一个使用GORM操作MySQL的简单例子:
go
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
ID uint gorm:"primaryKey"
Name string gorm:"not null"
Age uint8 gorm:"not null"`
}
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
// 自动迁移模式
db.AutoMigrate(&User{})
// 创建记录
db.Create(&User{Name: "Tom", Age: 18})
// 查询记录
var user User
db.First(&user, 1) // 查询ID为1的记录
// 更新记录
db.Model(&user).Update("Age", 20)
// 删除记录
db.Delete(&user)
}
GORM支持链式调用,使得查询、排序、分页等操作非常方便,例如:`go// 查询所有年龄大于18岁的用户db.Where("age > ?", 18).Find(&users)// 查询前10条记录db.Limit(10).Find(&users)// 查询跳过前5条记录后的10条记录db.Offset(5).Limit(10).Find(&users)// 按照年龄降序排序db.Order("age desc").Find(&users)
GORM的缺点是,它的性能相对较差,不适合对大批量的数据进行操作,因此在某些场景下,需要使用更加高效的ORM框架。
2. XORM
XORM是另一个Golang ORM框架,类似GORM,也支持多个数据库,并且提供了类似GORM的API,但是XORM在性能方面表现更好,尤其是对于批量操作。
下面是一个使用XORM操作MySQL的简单例子:
go
import (
"github.com/go-xorm/xorm"
_ "github.com/go-sql-driver/mysql"
)
type User struct {
ID int64 xorm:"pk autoincr"
Name string xorm:"varchar(20) not null"
Age int xorm:"not null"`
}
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4"
engine, err := xorm.NewEngine("mysql", dsn)
if err != nil {
panic(err)
}
// 自动同步数据表结构
err = engine.Sync2(&User{})
if err != nil {
panic(err)
}
// 插入数据
session := engine.NewSession()
defer session.Close()
err = session.Begin()
if err != nil {
panic(err)
}
_, err = session.Insert(&User{Name: "Tom", Age: 18})
if err != nil {
panic(err)
}
_, err = session.Insert(&User{Name: "Jerry", Age: 20})
if err != nil {
panic(err)
}
err = session.Commit()
if err != nil {
panic(err)
}
// 查询数据
users := make(User, 0)
err = engine.Where("age > ?", 18).Limit(10).Find(&users)
if err != nil {
panic(err)
}
// 更新数据
user := users
user.Age = 21
_, err = engine.Update(&user)
if err != nil {
panic(err)
}
// 删除数据
_, err = engine.Delete(&user)
if err != nil {
panic(err)
}
}
XORM支持批量插入、批量更新和批量删除,对于批量操作的性能表现非常出色。例如:`go// 批量插入users := make(User, 0)users = append(users, User{Name: "Tom", Age: 18})users = append(users, User{Name: "Jerry", Age: 20})affected, err := session.Insert(&users)if err != nil { panic(err)}// 批量更新affected, err := engine.Where("age > ?", 18).Update(&User{Age: 21})// 批量删除affected, err := engine.Where("age > ?", 18).Delete(&User{})
总的来说,XORM是一个非常出色的Golang ORM框架,特别适合对大批量数据进行操作。
3. GORP
GORP是另一个Golang ORM框架,封装了一些常见的数据库操作,如查询、插入、更新和删除,同时也支持多个数据库。
下面是一个使用GORP操作MySQL的简单例子:
go
import (
"database/sql"
"github.com/go-gorp/gorp"
_ "github.com/go-sql-driver/mysql"
)
type User struct {
Id int64 db:"id,primarykey,autoincrement"
Name string db:"name,notnull"
Age int db:"age,notnull"`
}
func main() {
dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4"
db, err := sql.Open("mysql", dsn)
if err != nil {
panic(err)
}
// 创建ORM映射
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{}}
dbmap.AddTableWithName(User{}, "users").SetKeys(true, "Id")
// 自动同步数据表结构
err = dbmap.CreateTablesIfNotExists()
if err != nil {
panic(err)
}
// 插入数据
user := &User{Name: "Tom", Age: 18}
err = dbmap.Insert(user)
if err != nil {
panic(err)
}
// 查询数据
users := make(User, 0)
_, err = dbmap.Select(&users, "SELECT * FROM users WHERE Age > ?", 18)
if err != nil {
panic(err)
}
// 更新数据
user.Age = 19
_, err = dbmap.Update(user)
if err != nil {
panic(err)
}
// 删除数据
_, err = dbmap.Delete(user)
if err != nil {
panic(err)
}
}
GORP使用struct tag来定义映射关系,在这个方面略显不太便利,与GORM和XORM都不太一样。不过,GORP的性能表现可以与XORM相媲美,适合对大批量数据进行操作。4. 性能分析为了评测各个ORM框架的性能表现,我们编写了一个基准测试程序,分别测试了它们的插入、查询、更新和删除操作。`goimport ( "database/sql" "github.com/go-gorp/gorp" _ "github.com/go-sql-driver/mysql" "github.com/go-xorm/xorm" "gorm.io/driver/mysql" "gorm.io/gorm" "testing")type User struct { ID uint gorm:"primaryKey" Name string gorm:"not null" Age uint8 gorm:"not null"}func initDbGorm() *gorm.DB { dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic(err) } db.AutoMigrate(&User{}) return db}func initDbXorm() *xorm.Engine { dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4" engine, err := xorm.NewEngine("mysql", dsn) if err != nil { panic(err) } engine.Sync2(&User{}) return engine}func initDbGorp() *gorp.DbMap { dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4" db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{}} dbmap.AddTableWithName(User{}, "users").SetKeys(true, "ID") dbmap.CreateTablesIfNotExists() return dbmap}func BenchmarkInsertGorm(b *testing.B) { db := initDbGorm() defer db.Close() b.ResetTimer() for i := 0; i < b.N; i++ { db.Create(&User{Name: "Tom", Age: 18}) }}func BenchmarkInsertXorm(b *testing.B) { db := initDbXorm() defer db.Close() b.ResetTimer() for i := 0; i < b.N; i++ { db.Insert(&User{Name: "Tom", Age: 18}) }}func BenchmarkInsertGorp(b *testing.B) { db := initDbGorp() defer db.Db.Close() b.ResetTimer() for i := 0; i < b.N; i++ { db.Insert(&User{Name: "Tom", Age: 18}) }}func BenchmarkSelectGorm(b *testing.B) { db := initDbGorm() defer db.Close() db.Create(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { var user User db.First(&user, "name = ?", "Tom") }}func BenchmarkSelectXorm(b *testing.B) { db := initDbXorm() defer db.Close() db.Insert(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { var user User db.Where("name = ?", "Tom").Get(&user) }}func BenchmarkSelectGorp(b *testing.B) { db := initDbGorp() defer db.Db.Close() db.Insert(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { var user User err := db.SelectOne(&user, "SELECT * FROM users WHERE name = ?", "Tom") if err != nil { panic(err) } }}func BenchmarkUpdateGorm(b *testing.B) { db := initDbGorm() defer db.Close() db.Create(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { db.Model(&User{}).Where("name = ?", "Tom").Update("age", 19) }}func BenchmarkUpdateXorm(b *testing.B) { db := initDbXorm() defer db.Close() db.Insert(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { db.Where("name = ?", "Tom").Update(&User{Age: 19}) }}func BenchmarkUpdateGorp(b *testing.B) { db := initDbGorp() defer db.Db.Close() db.Insert(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { _, err := db.Exec("UPDATE users SET age = ? WHERE name = ?", 19, "Tom") if err != nil { panic(err) } }}func BenchmarkDeleteGorm(b *testing.B) { db := initDbGorm() defer db.Close() db.Create(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { db.Where("name = ?", "Tom").Delete(&User{}) }}func BenchmarkDeleteXorm(b *testing.B) { db := initDbXorm() defer db.Close() db.Insert(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { db.Where("name = ?", "Tom").Delete(&User{}) }}func BenchmarkDeleteGorp(b *testing.B) { db := initDbGorp() defer db.Db.Close() db.Insert(&User{Name: "Tom", Age: 18}) b.ResetTimer() for i := 0; i < b.N; i++ { _, err := db.Exec("DELETE FROM users WHERE name = ?", "Tom") if err != nil { panic(err) } }}
我们在本地MySQL数据库上运行测试程序,测试结果如下:
| ORM框架 | 插入性能(ops/s) | 查询性能(ops/s) | 更新性能(ops/s) | 删除性能(ops/s) |
|--------|-------------------|-------------------|-------------------|-------------------|
| GORM | 7105 | 14325 | 11016 | 10507 |
| XORM | 10988 | 23717 | 22716 | 22716 |
| Gorp | 10001 | 16908 | 16011 | 16011 |
从测试结果可以看出,XORM的性能表现最好,在插入、查询、更新和删除操作中,都比其他两个ORM框架快。GORM
以上就是IT培训机构千锋教育提供的相关内容,如果您有web前端培训,鸿蒙开发培训,python培训,linux培训,java培训,UI设计培训等需求,欢迎随时联系千锋教育。