パフォーマンス

GORMは、パフォーマンスを向上させるために多くの最適化を行っています。デフォルトのパフォーマンスはほとんどのアプリケーションにとって良いものとなっているでしょう。 しかし、アプリケーションのパフォーマンスを向上させるいくつかのテクニックがまだあります。

デフォルトトランザクションを無効にする

GORMはデータの一貫性を確保するために、書き込み操作(作成/更新/削除)をトランザクション内で実行します。これはパフォーマンスにとっては悪影響を及ぼしますが、初期化時に無効にすることも可能です。

db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
SkipDefaultTransaction: true,
})

プリペアードステートメントをキャッシュする

SQLを実行する際にプリペアードステートメントを作成し、以降の呼び出しを高速化するためにそれをキャッシュすることができます。

// Globally mode
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
PrepareStmt: true,
})

// Session mode
tx := db.Session(&Session{PrepareStmt: true})
tx.First(&user, 1)
tx.Find(&users)
tx.Model(&user).Update("Age", 18)

ラウンドトリップを減らすためにMySQLのinterpolateparamsを有効にする方法も参照するとよいでしょう。 https://github.com/go-sql-driver/mysql#interpolateparams

プリペアードステートメントを用いたSQL Builder

プリペアードステートメントは RAW 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 Mode を使用してSQLの準備を行い、後の処理でそのSQLをプリペアードステートメントとともに実行することができます。詳細については、Session Mode を参照してください。

フィールドを選択する

デフォルトの設定では、クエリ実行時にすべてのフィールドが選択されます。 Select を使用して、必要なフィールドを指定できます。

db.Select("Name", "Age").Find(&Users{})

または、 便利なフィールドの選択 を使用するために、よりフィールド数を少なくした構造体を定義します。

type User struct {
ID uint
Name string
Age int
Gender string
// hundreds of fields
}

type APIUser struct {
ID uint
Name string
}

// Select `id`, `name` automatically when query
db.Model(&User{}).Limit(10).Find(&APIUser{})
// SELECT `id`, `name` FROM `users` LIMIT 10

Iteration / FindInBatches

イテレーションやバッチ処理でのクエリやレコード処理をすることも可能です。

インデックスヒント

Index はデータ検索とSQLクエリのパフォーマンスを高速化するために使用されます。 Index Hints は、クエリ処理で使用するべきインデックスの情報をオプティマイザに提供します。これにより、オプティマイザのものよりも効率的な実行計画を指定できるようになります。

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 Resolover を確認してください。

Platinum Sponsors

Gold Sponsors

Platinum Sponsors

Gold Sponsors