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()