😄
【Go】GORMのCreateInBatchesを使ってみる
はじめに
GORMのドキュメントを読んでいたところ、CreateInBatches
なるメソッドがあるのを見かけました。
どのように使うことができるのか、メモ的に書いてみようと思います。
環境
- go version go1.24.0 darwin/arm64
- macOS Sequoia 15.3.1
CreateInBatchesとは
CreateInBatches
func (db *DB) CreateInBatches(value interface{}, batchSize int) (tx *DB)
- GORMのDB型のメソッド
- 引数に登録したいデータとバッチサイズを渡す
- 大量のデータ(数万件や数十万件など)をデータベースに挿入する場合、一度にすべてを挿入しようとすると、メモリ消費が高くなったり、タイムアウトが発生したりすることがあるため、バッチサイズを指定することで負荷を軽減することができる
実装
今回はユーザーデータを100件登録するが、10件ずつに分けて登録するシチェーションで実装する
前提
- docker-compose.yamlでDBコンテナを作成・起動し、必要なテーブルを作成済み
- .envで環境変数を管理、対象のファイルで呼び出している
実装内容
エントリーポイント
main.go
package main
import (
"go-gorm/api"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.POST("/user", api.CreateUser)
e.Logger.Fatal(e.Start(":8080"))
}
DB情報
db.go
package db
import (
"fmt"
"log"
"os"
"github.com/joho/godotenv"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func NewDB() *gorm.DB {
if err := godotenv.Load(); err != nil {
log.Fatalln(err)
}
url := fmt.Sprintf("postgres://%s:%s@%s:%s/%s", os.Getenv("POSTGRES_USER"), os.Getenv("POSTGRES_PASSWORD"), os.Getenv("POSTGRES_HOST"), os.Getenv("POSTGRES_PORT"), os.Getenv("POSTGRES_DB"))
db, err := gorm.Open(postgres.Open(url))
if err != nil {
log.Fatalln(err)
}
return db
}
func CloseDB(db *gorm.DB) {
sqlDB, _ := db.DB()
if err := sqlDB.Close(); err != nil {
log.Fatalln(err)
}
}
User構造体を定義
user.go
package model
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
CreateInBatchesでデータを登録
create.go
package api
import (
"fmt"
"go-gorm/db"
"go-gorm/model"
"net/http"
"github.com/labstack/echo/v4"
)
func CreateUser(ctx echo.Context) error {
dbCon := db.NewDB()
defer db.CloseDB(dbCon)
users := make([]model.User, 100)
for i := 0; i < 100; i++ {
users[i] = model.User{Name: fmt.Sprintf("taro%d", i+1), Age: i + 1}
}
var count int
// バッチサイズの指定
batchSize := 10
for i := 0; i < len(users); i += batchSize {
end := i + batchSize
if end > len(users) {
end = len(users)
}
if err := dbCon.CreateInBatches(users[i:end], batchSize).Error; err != nil {
return err
}
count++
fmt.Printf("CreateInBatches%d回目\n", count)
}
return ctx.JSON(http.StatusOK, nil)
}
結果
ターミナル
CreateInBatches1回目
CreateInBatches2回目
CreateInBatches3回目
CreateInBatches4回目
CreateInBatches5回目
CreateInBatches6回目
CreateInBatches7回目
CreateInBatches8回目
CreateInBatches9回目
CreateInBatches10回目
postgres
name | age
---------+-----
taro1 | 1
taro2 | 2
taro3 | 3
taro4 | 4
taro5 | 5
taro6 | 6
taro7 | 7
taro8 | 8
taro9 | 9
taro10 | 10
(省略)
taro91 | 91
taro92 | 92
taro93 | 93
taro94 | 94
taro95 | 95
taro96 | 96
taro97 | 97
taro98 | 98
taro99 | 99
taro100 | 100
(100 rows)
まとめ
GORMのメソッドであるCreateInBatchesを使うことで、指定したバッチサイズに応じたデータ登録を行えること、またその実装方法について知ることができました。
他にGORMドキュメントを読んでみて面白そうなメソッドがあったら記事を書いてみようと思います!
Discussion