Django夹具加载速度很慢

时间:2013-10-10 21:46:34

标签: django postgresql django-fixtures

我正在尝试使用2套灯具提供初始数据。第一种灯具格式如下所示。

  {
    "pk": 1,
    "model": "data.Person",
    "fields": {
      "full": "Anna-Varney",
      "num": "I",
      "short": "Anna-Varney"
    }
  },

我首先加载它,并在大约1-2小时内加载。我的movie.json格式如下所示:

  {
    "pk": 1,
    "model": "data.Film",
    "fields": {
      "date": "2005-08-01",
      "rating": 8.3,
      "actors": [
        [
          "Anna-Varney"
        ]
      ],
      "name": "Like a Corpse Standing in Desperation (2005) (V)"
    }
  },

加载电影夹具已经花了很长时间,现在已经20小时了,我的电脑在运行时很迟钝。我在2个月前加载了类似的灯具,除了我使用MySQL(我现在使用Postgres)并且我在我的模型中添加了日期字段。在过去将电影装置加载到我的旧MySQL数据库中时,只花了2-3个小时。有没有办法确定夹具装载部件的步骤或是否已冻结?

作为参考我的模型是:

class PersonManager(models.Manager):
    def get_by_natural_key(self, full):
        return self.get(full=full)

class Person(models.Model):
    objects = PersonManager()
    full = models.CharField(max_length=100,unique = True)
    short = models.CharField(max_length=100)
    num = models.CharField(max_length=5)
    def natural_key(self):
        return (self.full,)

    def __unicode__(self):
        return self.full


class Film(models.Model):
    name = models.TextField()
    date = models.DateField()
    rating = models.DecimalField(max_digits=3 , decimal_places=1)
    actors = models.ManyToManyField('Person')

    def __unicode__(self):
        return self.name

3 个答案:

答案 0 :(得分:2)

如果您通过命令行加载灯具:

int

或者可能通过 shell 以编程方式:

python manage.py loaddata --database=MY_DB_LABEL fixtures/my_fixture.json;

夹具加载将。 (我还没有调查原因。大概是有很多不必要的中间数据库保存。)


解决方案:切换到使用单个事务通过 python 以编程方式加载您的装置:

os.system('python manage.py loaddata --database=%s fixtures/my_fixture.json;' % MY_DB_LABEL)

夹具加载将显着地加速。


请注意,此处的 from django.db import transaction from django.core.management import call_command with transaction.atomic(using=MY_DB_LABEL): call_command('loaddata', 'fixtures/my_fixture.json', database=MY_DB_LABEL) call_command('loaddata', 'fixtures/my_other_fixture.json', database=MY_DB_LABEL) database 参数是可选的。如果您使用的是单个数据库,则它们是不必要的。但是如果你像我一样使用多个数据库,你可能想用它来确保夹具数据加载到哪个数据库中。

答案 1 :(得分:0)

因为Django在自动提交模式下运行,所以它要求数据库确保在创建每个对象之后立即将其保存并同步到驱动器盘片上的物理位置。这会将保存的对象数量限制为磁盘盘片的速度。

您需要使用@transaction.atomic装饰器或with transaction.atomic():上下文管理器来允许数据库确保一切都安全地保存一次 - 最后。

您可以阅读more about transactions in Django documentation

我甚至建议在将PostgreSQL与Django一起使用时,在数据库配置中将ATOMIC_REQUESTS设置为True。这样,每个浏览器请求将自动在一个事务中提供,并且只有在成功运行视图时才会提交。

答案 2 :(得分:0)

在大多数情况下,您可以通过编程方式加载转储的数据并使用bulk_create

来加快处理速度

示例:

from collections import defaultdict
from django.core import serializers                                                                     

obj_dict = defaultdict(list)
deserialized = serializers.deserialize('json', open('my_fixtures.json'))
# organize by model class
for item in deserialized:
  obj = item.object
  obj_dict[obj.__class__].append(obj) 

for cls, objs in obj_dict.items():
  cls.objects.bulk_create(objs)