有效创建批量数据库条目?

时间:2011-10-27 20:42:33

标签: django

我正在尝试为Activty个对象的大型(一次300多个)列表创建一个Inquiry对象。我有一个ModelForm正在回发,我需要创建单独的实例,并通过Inquiry将它们附加到GenericForeignKey。我们来看一些代码:

models.py:

class InquiryEntry(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField() 
    entry = generic.GenericForeignKey('content_type', 'object_id')

class Inquiry(models.Model):
    entries = models.ManyToManyField('InquiryEntry')
    # And many more fields.
    def add_entry(self, obj):
        entry = self.entries.create(entry=obj)
        self.save()
        return entry

class Activity(models.Model):  
    ts = models.DateTimeField(auto_now_add=True)                  
    due_date = models.DateField(auto_now=False)
    ## And many more fields.

views.py:

def bulk_create_activities(request):
    activity_form = ActivityForm()
    if request.method == "POST":
        activity_form = ActivityForm(request.POST)
        if activity_form.is_valid():    
            pks = [int(x) for x in request.POST.get('pks', '').split(',')]
            for inquiry in Inquiry.objects.filter(pk__in=pks):
                instance = ActivityForm(request.POST).save()
                inquiry.add_entry(instance)     
                inquiry.save()  

我正在寻找的是一种将这些插入到数据库中的方法,最好是一次性传递,以便更快地处理请求。我不想放弃到数据库级别,因为这个应用程序是跨多个数据库供应商部署的,但如果这是继续进行的唯一方法,那么就是这样(MySQL和Postgres的例子很棒)。


注意:我知道开发版本中有bulk_create,但在发布稳定版之前,这是不可能的。

5 个答案:

答案 0 :(得分:3)

您是否尝试将for封装在事务构造中?成功提交事务可以大大提高速度,因为条目会批量写入磁盘,因此DBMS不必在每个项目后停止fsync()。

在最新版本的django中实现事务是快速的,请查看 https://docs.djangoproject.com/en/dev/topics/db/transactions/#controlling-transaction-management-in-views

答案 1 :(得分:1)

我担心您可能需要drop to DB-API并使用cursor.executemany()。有关详细信息,请参阅PEP 249

答案 2 :(得分:0)

您可以通过查看sql django生成的一些示例数据来获得一些提示(包括针对不同的数据库系统)。在调试模式下运行服务器将记录所有查询。你也可以通过

检查它们
>>> from django.db import connection
>>> connection.queries

答案 3 :(得分:0)

查看http://people.iola.dk/olau/python/bulkops.py

它提供执行单个查询的insert_many和update_many函数。正如作者所指出的那样,你必须在python中为许多关系中的pks做一些手动记账,但是一旦你完成它们,你就可以在InquiryInquiryEntry上执行几个insert_many的操作。

答案 4 :(得分:0)

这不会使您的批量操作更有效,但如果Inquiry不需要根​​据提交的数据即时响应(我假设基于型号名称),这听起来就像像芹菜这样的任务队列的完美工作。

用户将获得超快的响应,您的芹菜工人可以在闲暇时使用它。当1.4稳定时,请查看in_bulk:)

我也对数据库无关的坚如磐石的方法感兴趣,但根据你的情况,这可能是一个可接受的解决方案。

这里会看到答案......