【问题标题】:Slow saving to Django database缓慢保存到 Django 数据库
【发布时间】:2017-04-24 09:06:03
【问题描述】:

我创建了一个自定义的manage.py 命令,如下所示:

from django.contrib.auth.models import User
from django.core.management.base import BaseCommand
from photos.models import Person


class Command(BaseCommand):
    help = 'Pre-populate database with initial data'

    def _create_people(self, user):
        for i in range(0, 100):
            person = Person(first_name='FN', surname='SN', added_by=user)
            person.save()

    def handle(self, *args, **options):
        user = User.objects.get(username="user1")
        self._create_people(user)

我已经计时了 handle() 的执行时间,如果我不执行 person.save() 大约需要 0.02 秒,如果我保存的话,每个 Person 大约需要 0.1 秒。数据库是 sqlite,我相信它应该更快。什么可以解释如此糟糕的性能以及如何改进它?

【问题讨论】:

  • 这不是问题。只运行一次的命令需要 0.02 的时间,你甚至不需要花费一秒钟的时间。
  • @e4c5,同意,但事实并非如此。每个条目需要 0.1 秒,因此 3000 个条目需要 5 分钟。这只是一个模型。

标签: python django performance sqlite django-queryset


【解决方案1】:

分析:

def _create_people(self, user):
   for i in range(0, 100):
     person = Person(first_name='FN', surname='SN', added_by=user)
     # Hits the database for each save.
     person.save()

这个函数会命中数据库100次,每次都自动提交,这就是导致性能低下的原因(不考虑sqlite与MySQL或PostgreSQL相比的低性能)。

改进:

您需要的是bulk_create,它将使用类构造函数创建的对象数组作为输入。所以一个可能的解决方案如下:

def _create_people(self, user):
   person_data = {"first_name": "FN", "surname":"SN", "added_by": user}
   person_list = [Person(**person_data) for i in range(100)]
   Person.objects.bulk_create(person_list)

默认情况下,bulk_create 无论有多少对象都会命中数据库一次,SQLite 除外(在 SQLite 中,每个查询大约 999 个。)。 可以通过指定单个查询中可以创建多少个对象 参数batch_size

注意:

  • save()不会被调用,相关信号也不会被发送。
  • 不适用于 m2m 关系。

【讨论】:

  • bulk_create 是要走的路 +1
  • 太棒了。我不得不稍微修改一下代码,因为我认为 bulk_create 需要一个模型对象列表,而不是输入数据。所以更改为person_list.append(Person(first_name='FN', surname='SN', added_by=user)); Person.objects.bulk_create(person_list) 解决了问题(获取AttributeError: 'dict' object has no attribute 'pk')。
  • @texnic 你是对的,这是一个错字,我没有注意到 (y) 答案已更新;)
  • 性能大幅提升。只是 texnic 提到的修改。 “bulk_create 需要一个模型对象列表”
猜你喜欢
  • 2017-09-04
  • 1970-01-01
  • 2013-08-23
  • 2016-07-05
  • 1970-01-01
  • 2017-12-01
  • 2018-07-07
  • 1970-01-01
相关资源
最近更新 更多