2011-10-27 31 views
10

我正在嘗試爲Inquiry對象的大型(每次超過300個)列表創建一個Activty對象。我有一個正在發佈的ModelForm,我需要創建單獨的實例,並通過GenericForeignKey將它們附加到我的Inquiry。讓我們到一些代碼:高效創建批量數據庫條目?

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,但那是不可能的,直到有一個穩定的版本。

回答

3

您是否試圖簡單地將for放在事務構造中?提交成功事務可以讓你大幅加速,因爲條目具體寫入磁盤一次批量,所以DBMS不必停止在每個項目後的fsync()。

實現交易在最新版本的Django的是活潑的,檢查出 https://docs.djangoproject.com/en/dev/topics/db/transactions/#controlling-transaction-management-in-views

+0

看起來像一個好主意,但沒有改變性能。在5-10項活動中,速度提高了大約5%。在100,速度下降10%。 –

+0

感謝您的指針。這是一個很棒的新功能。 – AgDude

0

您可以通過查看SQL Django的得到一些提示(包括不同數據庫系統)生成一些樣本數據。以調試模式運行您的服務器所有查詢都會被記錄。您也可以通過

>>> from django.db import connection 
>>> connection.queries 
0

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

它提供了執行一個查詢insert_many和update_many功能。正如作者所指出的那樣,您將不得不在python中爲許多到很多關係做一些手動的簿記工作,但是一旦您完成了這些工作,您可以簡單地執行InquiryInquiryEntry上的insert_many對。

0

這不會使您的批量操作更加高效,但如果Inquiry不需要基於提交的數據即時響應(我假設基於型號名稱),這聽起來像是完美的爲Celery等任務隊列創建作業。

用戶會得到一個超級快速的反應,你的芹菜工人可以在他們的閒暇時間。當1.4穩定時,檢查in_bulk :)

我也會對數據庫不可知的岩石固體方法感興趣,但根據您的情況,這可能是一個可接受的解決方案。

將密切關注這裏的答案...