扫码一下
查看教程更方便
gorm 已经优化了许多东西来提高性能,其默认性能对大多数应用来说都够用了。但这里还是有一些关于如何为我们的应用改进性能的方法。
对于写操作(创建、更新、删除),为了确保数据的完整性,gorm 会将它们封装在一个事务里。但这会降低性能,你可以在初始化时禁用这种方式
db, err := gorm.open(sqlite.open("gorm.db"), &gorm.config{
skipdefaulttransaction: true,
})
执行任何 sql 时都创建并缓存预编译语句,可以提高后续的调用速度
// 全局模式
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)
注意
也可以参考如何为 mysql 开启 interpolateparams 以减少 roundtriphttps://github.com/go-sql-driver/mysql#interpolateparams
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)
我们也可以使用 gorm 的 api dryrun 模式 编写 sql 并执行 prepared statement ,查看 会话模式 获取详情
默认情况下,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
用迭代或 in batches 查询并处理记录
index 用于提高数据检索和 sql 查询性能。 index hints 向优化器提供了在查询处理过程中如何选择索引的信息。与 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`)"
通过读写分离提高数据吞吐量,查看 database resolver 获取详情