GORM 已经优化了许多东西来提高性能,其默认性能对大多数应用来说都够用了。但这里还是有一些关于如何为您的应用改进性能的方法。
禁用默认事务
对于写操作(创建、更新、删除),为了确保数据的完整性,GORM 会将它们封装在事务内运行。但这会降低性能,你可以在初始化时禁用这种方式
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
SkipDefaultTransaction: true,
})
缓存 Prepared Statement
执行任何 SQL 时都创建 prepared statement 并缓存,可以提高后续的调用速度
// 全局模式
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
PrepareStmt: true,
})
// 会话模式
tx := db.Session(&Session{PrepareStmt: true})
tx.First(&user, 1)
tx.Find(&users)
tx.Model(&user).Update("Age", 18)
带 PreparedStmt 的 SQL 生成器
Prepared Statement 也可以和原生 SQL 一起使用,例如:
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
PrepareStmt: true,
})
db.Raw("select sum(age) from users where role = ?", "admin").Scan(&age)
You can also use GORM API to prepare SQL with DryRun Mode, and execute it with prepared statement later, checkout Session Mode for details
选择字段
默认情况下,GORM 在查询时会选择所有的字段,您可以使用 Select
来指定您想要的字段
db.Select("Name", "Age").Find(&Users{})
或者定义一个较小的 API 结构体,使用 智能选择字段功能
type User struct {
ID uint
Name string
Age int
Gender string
// 假设后面还有几百个字段...
}
type APIUser struct {
ID uint
Name string
}
// 查询时会自动选择 `id`、`name` 字段
db.Model(&User{}).Limit(10).Find(&APIUser{})
// SELECT `id`, `name` FROM `users` LIMIT 10
Iteration / FindInBatches
Query and process records with iteration or in batches
Index Hints
Index is used to speed up data search and SQL query performance. Index Hints
gives the optimizer information about how to choose indexes during query processing, which gives the flexibility to choose a more efficient execution plan than the optimizer
import "gorm.io/hints"
DB.Clauses(hints.UseIndex("idx_user_name")).Find(&User{})
// SELECT * FROM `users` USE INDEX (`idx_user_name`)
DB.Clauses(hints.ForceIndex("idx_user_name", "idx_user_id").ForJoin()).Find(&User{})
// SELECT * FROM `users` FORCE INDEX FOR JOIN (`idx_user_name`,`idx_user_id`)"
DB.Clauses(
hints.ForceIndex("idx_user_name", "idx_user_id").ForOrderBy(),
hints.IgnoreIndex("idx_user_name").ForGroupBy(),
).Find(&User{})
// SELECT * FROM `users` FORCE INDEX FOR ORDER BY (`idx_user_name`,`idx_user_id`) IGNORE INDEX FOR GROUP BY (`idx_user_name`)"