DjangoBrothers BLOG ✍️

2019/11/16

このエントリーをはてなブックマークに追加
Django モデル SQL データベース パフォーマンス向上

【Django】複数オブジェクトを効率よく作成・更新するbulk_create, bulk_updateの使い方

大量のオブジェクトを作成したい時には、create()メソッドを何回も繰り返し実行するのではなく、bulk_create()メソッドを使った方が圧倒的に効率よくデータをDBに登録できます。

以下のモデルを例に、bulk_create()、bulk_update()の使い方を説明します。

models.py

class User(models.Model):
    name = models.CharField(max_length=50)

bulk_create()の使い方

まずは、create()メソッドを使って、10万件Userオブジェクトを登録する例です。

create()メソッドを10万回実行する

for _ in range(100000):
    User.objects.create(name="jobs")

この場合、10万回クエリが実行されるので、実行完了まで非常に時間がかかります。 私の環境の場合、107.63秒かかりました。

次に、bulk_create()メソッドを使ってみます。bulk_create()メソッドには、引数として、オブジェクトのリストを渡します。

bulk_create()メソッドを使う

# 10万件のUserオブジェクトが入ったリストを作る(この段階ではDBに登録されない)
user_objects = []
for _ in range(100000):
    user_objects.append(User(name="jobs"))

# user_objects のデータをDBに一括登録する
User.objects.bulk_create(user_objects)

bulk_create()メソッドは、オブジェクトがいくつあろうと1回しかクエリが実行されないため、早く処理が完了します。 計測結果は1.36秒でした。create()メソッドより、相当効率よく処理が行われます。

注意点

bulk_create()には以下のような注意点があります。

  • モデルのsave()メソッドは呼ばれず、pre_save(), post_save()シグナルも送信されません。
  • many-to-manyフィールドの値を指定してbulk_create()はできない。(ただし、中間テーブルとなっているモデルでbulk_create()することで、多対多の関係性を一括作成することはできます。)

bulk_update()の使い方

Django2.2からはbulk_update()が使えるようになりました。 それぞれのnameに"さん"を加えて更新してみます。

bulk_update()を使う

users = User.objects.all()
for user in users:
    user.name = user.name + "さん"

# users のデータを一括更新
User.objects.bulk_update(users, fields=["name"])

以下のように1回1回save()を呼び出すより、かなり早く処理が終了します。

bulk_update()を使わない場合

users = User.objects.all()
for user in users:
    user.name = user.name + "さん"
    user.save()

参考