web-dev-qa-db-ja.com

Djangoを使用して何千ものレコードをSQLiteテーブルに挿入する効率的な方法は何ですか?

DjangoのORMを使用して、8000以上のレコードをSQLiteデータベースに挿入する必要があります。この操作は、cronjobとして約1分に1回実行する必要があります。
現時点では、forループを使用してすべてのアイテムを繰り返し処理し、それらを1つずつ挿入しています。
例:

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

これを行う効率的な方法は何ですか?

編集: 2つの挿入方法の小さな比較。

Commit_manuallyデコレーターなし(11245レコード):

nox@noxdevel marinetraffic]$ time python manage.py insrec             

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

Commit_manuallyデコレータを使用する(11245レコード):

[nox@noxdevel marinetraffic]$ time python manage.py insrec                

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

注:testスクリプトは、データベースへの挿入(Zipファイルのダウンロード、XMLファイルの抽出)以外のいくつかの操作も行いますZipアーカイブからXMLファイルを解析します)。実行に必要な時間は、必ずしもレコードの挿入に必要な時間を表すとは限りません。

67
user11617

チェックアウトしたいDjango.db.transaction.commit_manually

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

したがって、次のようになります。

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

代わりに、各save()で1回だけコミットします。

In Django 1.3コンテキストマネージャーが導入されました。したがって、transaction.commit_on_success()を同様の方法で使用できます:

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 が追加され、モデルオブジェクトのリストを作成し、それらを一度にコミットできるようになりました。

[〜#〜] note [〜#〜]一括作成を使用する場合、saveメソッドは呼び出されません。

>>> 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が導入され、現在はレガシー関数commit_on_successおよびcommit_manually

Django atomicに関するドキュメント

atomicはデコレーターとしても使用できます:

from Django.db import transaction

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

コンテキストマネージャーとして:

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
11
A-IV

this をご覧ください。これは、MySQLですぐに使用できるように意図されていますが、他のデータベースで何をすべきかについての指針があります。

3
Vinay Sajip

アイテムを一括ロードする方がよい場合があります-ファイルを準備し、一括ロードツールを使用します。これは、8000個の個別の挿入よりもはるかに効率的です。

[〜#〜] dse [〜#〜] をチェックアウトする必要があります。この種の問題(大量の挿入または更新)を解決するためにDSEを作成しました。 Django ormは行き止まりです。プレーンSQLでそれを行う必要があり、DSEがそのほとんどを処理します。

トーマス

2
Weholt

特にSQLiteに関する質問に答えるために、尋ねたように、bulk_createが大幅な高速化を提供することを確認したばかりですが、SQLiteには制限があります。「デフォルトでは、SQLiteを除くすべてのオブジェクトをデフォルトでは、クエリごとに最大999個の変数が使用されます。」

引用されたものはドキュメントからです--- A-IVはリンクを提供しました。

私が追加しなければならないのは、 this djangosnippets alparのエントリも私にとってはうまく機能しているようだということです。 999個の変数の制限を管理して、処理したい大きなバッチを小さなバッチに分割する小さなラッパーです。

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