LoginSignup
0
0

More than 1 year has passed since last update.

(備忘メモ)Django + MySQL で大量データを insert しつつ ID を取得したい場合

Posted at

Django + MySQL でバッチ的にデータの登録を行いたかったのですが、微妙にテクニカルだったので備忘メモ

bulk_insert では ID が拾えない

対応策:通常のインサートを行いつつ、トランザクションを広めに取る

  • 通常、Django は一回の insert ごとにトランザクションを貼る。
  • これをまとめることで、性能改善が望める。

検証

条件

  • MacBook Pro (13-inch, 2020)
    • 1.4 GHz Quad-Core Intel Core i5
  • MySQL 5.7
  • Django 1.11.18

サンプルコード

# ディレクトリ構成
├── tmp_multi_insert_test
│   ├── __init__.py
│   ├── models.py
│   └── script.py
├── manage.py
# models.py
from django.db import models

class test_model(models.Model):
    name = models.CharField(max_length=60)
# script.py
# 100 件ごとにテスト
import timeit

from django.db import transaction

from models import test_model

def insert_in_loop(repeat=100):
    ids = \[]
    for i in range(repeat):
        new_model = test_model(name='tmp_{}'.format(i))
        new_model.save()
        ids.append(new_model.id)
    return ids

def insert(repeat=100, with_transaction=True):
    if with_transaction:
        with transaction.atomic():
            ids = insert_in_loop(repeat)
    else:
        ids = insert_in_loop(repeat)

start = timeit.default_timer()
insert(with_transaction=False) # 引数を切り替えながらテストする
stop = timeit.default_timer()
print(stop - start) 

実行方法

$ ./manage.py shel
>>> exec(open('./tmp_multi_insert_test/script.py').read())
Time:  0.49636074993759394

結果

各 10 回ぐらいずつやった平均値

トランザクションあり トランザクションなし
0.094 0.480

およそ 5 倍の速度差がありました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0