it-swarm.com.de

Was ist eine effiziente Möglichkeit, mit Django Tausende von Datensätzen in eine SQLite-Tabelle einzufügen?

Ich muss über 8000 Datensätze mit Djangos ORM in eine SQLite-Datenbank einfügen. Dieser Vorgang muss ungefähr einmal pro Minute als Cronjob ausgeführt werden.
Im Moment benutze ich eine for-Schleife, um alle Elemente zu durchlaufen und sie dann einzeln einzufügen.
Beispiel:

for item in items:
    entry = Entry(a1=item.a1, a2=item.a2)
    entry.save()

Was ist ein effizienter Weg, um dies zu tun?

Edit: Ein kleiner Vergleich zwischen den beiden Einfügemethoden.

Ohne commit_manually decorator (11245 Datensätze):

[email protected] marinetraffic]$ time python manage.py insrec             

real    1m50.288s
user    0m6.710s
sys     0m23.445s

Verwenden von commit_manually decorator (11245 Datensätze):

[[email protected] marinetraffic]$ time python manage.py insrec                

real    0m18.464s
user    0m5.433s
sys     0m10.163s

Hinweis: Das Skript test führt neben dem Einfügen in die Datenbank (Herunterladen einer Zip-Datei, Extrahieren einer XML-Datei) auch einige andere Vorgänge aus Analysiert die XML-Datei aus dem Zip-Archiv, sodass die für die Ausführung erforderliche Zeit nicht unbedingt der Zeit entspricht, die zum Einfügen der Datensätze erforderlich ist.

67
user11617

Sie möchten Django.db.transaction.commit_manually Auschecken.

http://docs.djangoproject.com/en/dev/topics/db/transactions/#Django-db-transaction-commit-manually

Es wäre also so etwas wie:

from Django.db import transaction

@transaction.commit_manually
def viewfunc(request):
    ...
    for item in items:
        entry = Entry(a1=item.a1, a2=item.a2)
        entry.save()
    transaction.commit()

Was nur einmal festgeschrieben wird, stattdessen bei jedem Speichern ().

In Django 1.3 wurden Kontextmanager eingeführt. Nun können Sie transaction.commit_on_success () in einer ähnlichen Weise:

from Django.db import transaction

def viewfunc(request):
    ...
    with transaction.commit_on_success():
        for item in items:
            entry = Entry(a1=item.a1, a2=item.a2)
            entry.save()

In Django 1.4, bulk_create wurde hinzugefügt, sodass Sie Listen Ihrer Modellobjekte erstellen und dann alle auf einmal festschreiben können.

[~ # ~] note [~ # ~] Die Speichermethode wird bei Verwendung der Massenerstellung nicht aufgerufen.

>>> Entry.objects.bulk_create([
...     Entry(headline="Django 1.0 Released"),
...     Entry(headline="Django 1.1 Announced"),
...     Entry(headline="Breaking: Django is awesome")
... ])

In Django 1.6, transaction.atomic wurde eingeführt, um jetzt Legacy-Funktionen zu ersetzen commit_on_success Und commit_manually.

aus der Django Dokumentation zu Atomic :

atomic ist sowohl als Dekorateur verwendbar:

from Django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

und als Kontextmanager:

from Django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()
118
monkut

Die Massenerstellung ist in Django 1.4 verfügbar:

https://Django.readthedocs.io/de/1.4/ref/models/querysets.html#bulk-create

11
A-IV

Schauen Sie sich this an. Es ist nur für die sofortige Verwendung mit MySQL vorgesehen, es gibt jedoch Hinweise, was für andere Datenbanken zu tun ist.

3
Vinay Sajip

Möglicherweise ist es besser, wenn Sie die Elemente in großen Mengen laden - bereiten Sie eine Datei vor und verwenden Sie ein Massenladetool. Dies ist weitaus effizienter als 8000 einzelne Einsätze.

Sie sollten auschecken DSE . Ich habe DSE geschrieben, um diese Probleme zu lösen (massive Einfügung oder Updates). Die Verwendung des Orms Django ist eine Sackgasse, Sie müssen dies in einfachem SQL tun, und DSE erledigt vieles für Sie.

Thomas

2
Weholt

Zur Beantwortung der Frage, insbesondere in Bezug auf SQLite, habe ich gerade bestätigt, dass bulk_create eine enorme Geschwindigkeitssteigerung bietet. In SQLite gibt es jedoch eine Einschränkung: "Standardmäßig werden alle Objekte in einem Stapel erstellt, mit Ausnahme von SQLite, in dem Standardmäßig werden maximal 999 Variablen pro Abfrage verwendet. "

Das zitierte Zeug stammt aus den Dokumenten --- A-IV hat einen Link bereitgestellt.

Was ich hinzufügen muss, ist, dass dieser Djangosnippets Eintrag von alpar auch für mich zu arbeiten scheint. Es ist ein kleiner Wrapper, der den großen Stapel, den Sie verarbeiten möchten, in kleinere Stapel aufteilt und das Limit von 999 Variablen verwaltet.

2
Mike O'Connor
def order(request):    
    if request.method=="GET":
        # get the value from html page
        cust_name = request.GET.get('cust_name', '')
        cust_cont = request.GET.get('cust_cont', '')
        pincode = request.GET.get('pincode', '')
        city_name = request.GET.get('city_name', '')
        state = request.GET.get('state', '')
        contry = request.GET.get('contry', '')
        gender = request.GET.get('gender', '')
        paid_amt = request.GET.get('paid_amt', '')
        due_amt = request.GET.get('due_amt', '')
        order_date = request.GET.get('order_date', '')
        prod_name = request.GET.getlist('prod_name[]', '')
        prod_qty = request.GET.getlist('prod_qty[]', '')
        prod_price = request.GET.getlist('prod_price[]', '')

        # insert customer information into customer table
        try:
            # Insert Data into customer table
            cust_tab = Customer(customer_name=cust_name, customer_contact=cust_cont, gender=gender, city_name=city_name, pincode=pincode, state_name=state, contry_name=contry)
            cust_tab.save()
            # Retrive Id from customer table
            custo_id = Customer.objects.values_list('customer_id').last()   #It is return Tuple as result from Queryset
            custo_id = int(custo_id[0]) #It is convert the Tuple in INT
            # Insert Data into Order table
            order_tab = Orders(order_date=order_date, paid_amt=paid_amt, due_amt=due_amt, customer_id=custo_id)
            order_tab.save()
            # Insert Data into Products table
            # insert multiple data at a one time from djanog using while loop
            i=0
            while(i<len(prod_name)):
                p_n = prod_name[i]
                p_q = prod_qty[i]
                p_p = prod_price[i]

                # this is checking the variable, if variable is null so fill the varable value in database
                if p_n != "" and p_q != "" and p_p != "":
                    prod_tab = Products(product_name=p_n, product_qty=p_q, product_price=p_p, customer_id=custo_id)
                    prod_tab.save()
                i=i+1

            return HttpResponse('Your Record Has been Saved')
        except Exception as e:
            return HttpResponse(e)     

    return render(request, 'invoice_system/order.html')
0
Mohit Mishra