Toplu veritabanı girişleri verimli bir şekilde oluşturulsun mu?

Sorgulama nesnelerinin büyük (bir seferde 300'den fazla) listesi için Activty nesnesi oluşturmaya çalışıyorum. Geri gönderilmekte olan tek bir ModelForm var ve ayrı örnekler oluşturmam gerekiyor ve bunları GenericForeignKey aracılığıyla Sorgulama 'na eklemeliyim. Hadi bir kod alalım:

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()  

Aradığım şey, veritabanının içine, tercihan tek geçişte eklenerek, talebin daha hızlı işlenebilmesi için bir yoldur. Bu uygulama birden fazla veritabanı satıcısı arasında dağıtıldığı için veritabanı düzeyine düşmemeyi tercih ediyorum, ancak bu devam etmenin tek yolu buysa, o zaman (MySQL ve Postgres için örnekler harika olurdu).


Note: I know that there is a bulk_create in the development version, but that is out of the question until there is a stable release.

10

5 cevap

Bir işlem yapısında için 'i kolayca eklemeyi denediniz mi? Başarıya bağlı işlemler size büyük hızlı artışlar sağlayabilir, çünkü girdiler somut olarak tek seferde diske toplu olarak yazılır, bu nedenle DBMS, her öğeden sonra fsync() için durmak zorunda kalmaz.

Implementing transactions in recent versions of django is snappy, check out https://docs.djangoproject.com/en/dev/topics/db/transactions/#controlling-transaction-management-in-views

3
katma
İyi bir fikir gibi görünüyor ama performansı çok fazla değiştirmedim. 5-10 Aktivitelerde, yaklaşık% 5'lik bir hız artışı vardı. 100'de% 10'luk bir hız azalması.
katma yazar Jack M., kaynak
İşaretçi için teşekkürler. Bu yeni ve harika bir özellik.
katma yazar AgDude, kaynak

Korkarım, adresine gitmeniz gerekebilir. DB-API ve cursor.executemany() kullanın. Ayrıntılar için PEP 249 sayfasına bakın.

1
katma

Bu, toplu işleminizi daha verimli hale getirmez, ancak bir Sorgulama 'nun gönderilen verilere dayanarak anlık olarak yanıtlanması gerekmiyorsa (model adına dayalı varsayım), bu sesler Kereviz gibi bir iş kuyruğu için mükemmel bir iş gibi.

Kullanıcı süper hızlı bir yanıt alacaktır ve kereviz işçileriniz boş zamanlarında çırpınabilir. 1.4 kararlı olduğunda, in_bulk'a bakın :)

Ayrıca bir veritabanı agnostik kaya katı yöntemi ile ilgilenmek istiyorum ama durumunuza bağlı olarak bu kabul edilebilir bir çözüm olabilir.

Cevapları burada izleyecek ...

0
katma

Take a look at http://people.iola.dk/olau/python/bulkops.py

Tek bir sorguyu yürüten insert_many ve update_many işlevlerini sağlar. Yazarın belirttiği gibi, pek çok ilişkide pks için python'da bazı manuel defter tutma yapmak zorunda kalacaksınız, ancak bunları bir kez yaptıktan sonra, Inquiry ve InquiryEntry .

0
katma

Bazı örnek veriler için sql django'yu oluşturarak bazı ipuçlarını (farklı db sistemleri dahil) edinebilirsiniz. sunucunuzu hata ayıklama modunda çalıştırdığınızda tüm sorgular günlüğe kaydedilir. bunları da inceleyebilirsiniz

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