Zenn
😄

【Go】GORMのCreateInBatchesを使ってみる

2025/03/10に公開

はじめに

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

ログインするとコメントできます