# 性能
GORM 已經優化了許多東西來提高性能,其默認性能對大多數應用來說都夠用了。但這里還是有一些關于如何為您的應用改進性能的方法。
## [禁用默認事務](http://v2.gorm.io/zh_CN/docs/transactions.html)
對于寫操作(創建、更新、刪除),為了確保數據的完整性,GORM 會將它們封裝在事務內運行。但這會降低性能,你可以在初始化時禁用這種方式
```go
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
SkipDefaultTransaction: true,
})
```
## [緩存 Prepared Statement](http://v2.gorm.io/zh_CN/docs/session.html)
執行任何 SQL 時都創建 prepared statement 并緩存,可以提高后續的調用速度
```go
// 全局模式
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 生成器](http://v2.gorm.io/zh_CN/docs/sql_builder.html)
Prepared Statement 也可以和原生 SQL 一起使用,例如:
```go
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 模式](http://v2.gorm.io/zh_CN/docs/session.html) 編寫 SQL 并執行 prepared statement ,查看 [會話模式](http://v2.gorm.io/zh_CN/docs/session.html) 獲取詳情
## 選擇字段
默認情況下,GORM 在查詢時會選擇所有的字段,您可以使用 `Select` 來指定您想要的字段
```go
db.Select("Name", "Age").Find(&Users{})
```
或者定義一個較小的 API 結構體,使用 [智能選擇字段功能](http://v2.gorm.io/zh_CN/docs/advanced_query.html)
```go
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
```
## [迭代、FindInBatches](http://v2.gorm.io/zh_CN/docs/advanced_query.html)
用迭代或 in batches 查詢并處理記錄
## [索引提示](http://v2.gorm.io/zh_CN/docs/hints.html)
[索引](http://v2.gorm.io/zh_CN/docs/indexes.html) 用于提高數據檢索和 SQL 查詢性能。 `索引提示` 向優化器提供了在查詢處理過程中如何選擇索引的信息。與 optimizer 相比,它可以更靈活地選擇更有效的執行計劃
```go
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`)"
```