Golang中的ORM框架評(píng)測(cè)及性能分析
ORM是對(duì)象關(guān)系映射(Object-Relational Mapping)的縮寫,是一種通過(guò)使用描述對(duì)象和數(shù)據(jù)庫(kù)之間映射的元數(shù)據(jù),將面向?qū)ο笳Z(yǔ)言程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫(kù)中的技術(shù)。在Golang中,ORM框架也是非常重要的,因?yàn)樗梢詭椭覀兒?jiǎn)化數(shù)據(jù)庫(kù)操作的復(fù)雜度,提高開(kāi)發(fā)效率。本文將會(huì)對(duì)Golang中的ORM框架進(jìn)行評(píng)測(cè)及性能分析,以便讀者能夠選擇適合自己的ORM框架。
1. GORM
GORM是一個(gè)比較流行的Golang ORM框架,它提供了非常多的特性和工具,方便我們進(jìn)行數(shù)據(jù)庫(kù)操作。GORM支持MySQL、SQLite、PostgreSQL、SQL Server等多個(gè)數(shù)據(jù)庫(kù),并且允許我們定義模型結(jié)構(gòu)體,對(duì)模型的增刪改查都提供了非常友好的接口。
下面是一個(gè)使用GORM操作MySQL的簡(jiǎn)單例子:
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)
}
// 自動(dòng)遷移模式
db.AutoMigrate(&User{})
// 創(chuàng)建記錄
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支持鏈?zhǔn)秸{(diào)用,使得查詢、排序、分頁(yè)等操作非常方便,例如:`go// 查詢所有年齡大于18歲的用戶db.Where("age > ?", 18).Find(&users)// 查詢前10條記錄db.Limit(10).Find(&users)// 查詢跳過(guò)前5條記錄后的10條記錄db.Offset(5).Limit(10).Find(&users)// 按照年齡降序排序db.Order("age desc").Find(&users)
GORM的缺點(diǎn)是,它的性能相對(duì)較差,不適合對(duì)大批量的數(shù)據(jù)進(jìn)行操作,因此在某些場(chǎng)景下,需要使用更加高效的ORM框架。
2. XORM
XORM是另一個(gè)Golang ORM框架,類似GORM,也支持多個(gè)數(shù)據(jù)庫(kù),并且提供了類似GORM的API,但是XORM在性能方面表現(xiàn)更好,尤其是對(duì)于批量操作。
下面是一個(gè)使用XORM操作MySQL的簡(jiǎn)單例子:
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)
}
// 自動(dòng)同步數(shù)據(jù)表結(jié)構(gòu)
err = engine.Sync2(&User{})
if err != nil {
panic(err)
}
// 插入數(shù)據(jù)
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)
}
// 查詢數(shù)據(jù)
users := make(User, 0)
err = engine.Where("age > ?", 18).Limit(10).Find(&users)
if err != nil {
panic(err)
}
// 更新數(shù)據(jù)
user := users
user.Age = 21
_, err = engine.Update(&user)
if err != nil {
panic(err)
}
// 刪除數(shù)據(jù)
_, err = engine.Delete(&user)
if err != nil {
panic(err)
}
}
XORM支持批量插入、批量更新和批量刪除,對(duì)于批量操作的性能表現(xiàn)非常出色。例如:`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{})
總的來(lái)說(shuō),XORM是一個(gè)非常出色的Golang ORM框架,特別適合對(duì)大批量數(shù)據(jù)進(jìn)行操作。
3. GORP
GORP是另一個(gè)Golang ORM框架,封裝了一些常見(jiàn)的數(shù)據(jù)庫(kù)操作,如查詢、插入、更新和刪除,同時(shí)也支持多個(gè)數(shù)據(jù)庫(kù)。
下面是一個(gè)使用GORP操作MySQL的簡(jiǎn)單例子:
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)
}
// 創(chuàng)建ORM映射
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{}}
dbmap.AddTableWithName(User{}, "users").SetKeys(true, "Id")
// 自動(dòng)同步數(shù)據(jù)表結(jié)構(gòu)
err = dbmap.CreateTablesIfNotExists()
if err != nil {
panic(err)
}
// 插入數(shù)據(jù)
user := &User{Name: "Tom", Age: 18}
err = dbmap.Insert(user)
if err != nil {
panic(err)
}
// 查詢數(shù)據(jù)
users := make(User, 0)
_, err = dbmap.Select(&users, "SELECT * FROM users WHERE Age > ?", 18)
if err != nil {
panic(err)
}
// 更新數(shù)據(jù)
user.Age = 19
_, err = dbmap.Update(user)
if err != nil {
panic(err)
}
// 刪除數(shù)據(jù)
_, err = dbmap.Delete(user)
if err != nil {
panic(err)
}
}
GORP使用struct tag來(lái)定義映射關(guān)系,在這個(gè)方面略顯不太便利,與GORM和XORM都不太一樣。不過(guò),GORP的性能表現(xiàn)可以與XORM相媲美,適合對(duì)大批量數(shù)據(jù)進(jìn)行操作。4. 性能分析為了評(píng)測(cè)各個(gè)ORM框架的性能表現(xiàn),我們編寫了一個(gè)基準(zhǔn)測(cè)試程序,分別測(cè)試了它們的插入、查詢、更新和刪除操作。`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) } }}
我們?cè)诒镜豈ySQL數(shù)據(jù)庫(kù)上運(yùn)行測(cè)試程序,測(cè)試結(jié)果如下:
| ORM框架 | 插入性能(ops/s) | 查詢性能(ops/s) | 更新性能(ops/s) | 刪除性能(ops/s) |
|--------|-------------------|-------------------|-------------------|-------------------|
| GORM | 7105 | 14325 | 11016 | 10507 |
| XORM | 10988 | 23717 | 22716 | 22716 |
| Gorp | 10001 | 16908 | 16011 | 16011 |
從測(cè)試結(jié)果可以看出,XORM的性能表現(xiàn)最好,在插入、查詢、更新和刪除操作中,都比其他兩個(gè)ORM框架快。GORM
以上就是IT培訓(xùn)機(jī)構(gòu)千鋒教育提供的相關(guān)內(nèi)容,如果您有web前端培訓(xùn),鴻蒙開(kāi)發(fā)培訓(xùn),python培訓(xùn),linux培訓(xùn),java培訓(xùn),UI設(shè)計(jì)培訓(xùn)等需求,歡迎隨時(shí)聯(lián)系千鋒教育。