UFO ET IT

Django를 사용하여 SQLite 테이블에 수천 개의 레코드를 삽입하는 효율적인 방법은 무엇입니까?

ufoet 2020. 11. 10. 22:41
반응형

Django를 사용하여 SQLite 테이블에 수천 개의 레코드를 삽입하는 효율적인 방법은 무엇입니까?


Django의 ORM을 사용하여 8000 개 이상의 레코드를 SQLite 데이터베이스에 삽입해야합니다. 이 작업은 분당 약 한 번 cronjob으로 실행해야합니다.
지금은 for 루프를 사용하여 모든 항목을 반복 한 다음 하나씩 삽입합니다.
예:

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

이를 수행하는 효율적인 방법은 무엇입니까?

편집 : 두 삽입 방법 사이의 약간의 비교.

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

참고 : 테스트 스크립트는 (다운로드에게 ZIP 파일을 ZIP 아카이브에서 XML 파일을 추출, XML 파일을 구문 분석) 데이터베이스에 삽입 외에 다른 작업을 수행 반드시 시간을 나타내지 않는 실행을 위해 필요한 시간은 삽입에 필요한 있도록 기록.


당신은 체크 아웃하고 싶다 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 ()에서 한 번만 커밋됩니다.

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

django 1.4에서는 bulk_create모델 객체 목록을 만든 다음 한 번에 모두 커밋 할 수 있도록 추가되었습니다.

참고 대량 생성을 사용할 때는 save 메서드가 호출되지 않습니다.

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

django 1.6에서 transaction.atomic 이 도입되어 이제 레거시 함수 commit_on_successcommit_manually.

atomic에 대한 django 문서에서 :

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

Django 1.4에서 대량 생성이 가능합니다.

https://django.readthedocs.io/en/1.4/ref/models/querysets.html#bulk-create


이것 좀보세요 . 이는 MySQL에서만 기본적으로 사용하기위한 것이지만 다른 데이터베이스에 대해 수행 할 작업에 대한 지침이 있습니다.


항목을 대량으로로드하는 것이 더 나을 수 있습니다. 파일을 준비하고 대량로드 도구를 사용하십시오. 이것은 8000 개의 개별 인서트보다 훨씬 더 효율적입니다.


DSE를 확인해야합니다 . 이러한 종류의 문제 (대량 삽입 또는 업데이트)를 해결하기 위해 DSE를 작성했습니다. django orm을 사용하는 것은 막 다른 길이며, 일반 SQL로해야하며 DSE가 그 대부분을 처리합니다.

도마


특히 SQLite와 관련된 질문에 대답하기 위해 저는 bulk_create가 엄청난 속도 향상을 제공한다는 것을 방금 확인했지만 SQLite에는 제한이 있습니다. "기본값은 SQLite를 제외하고 모든 개체를 한 번에 생성하는 것입니다. 기본값은 쿼리 당 최대 999 개의 변수가 사용되는 것입니다. "

인용 된 내용은 문서에서 가져온 것입니다 --- A-IV가 링크를 제공했습니다.

What I have to add is that this djangosnippets entry by alpar also seems to be working for me. It's a little wrapper that breaks the big batch that you want to process into smaller batches, managing the 999 variables limit.


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

I recommend using plain SQL (not ORM) you can insert multiple rows with a single insert:

insert into A select from B;

The select from B portion of your sql could be as complicated as you want it to get as long as the results match the columns in table A and there are no constraint conflicts.


def order(request):    
    if request.method=="GET":
        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', '')
        print(order_date)
        prod_name = request.GET.getlist('prod_name[]', '')
        prod_qty = request.GET.getlist('prod_qty[]', '')
        prod_price = request.GET.getlist('prod_price[]', '')
        print(prod_name)
        print(prod_qty)
        print(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

참고URL : https://stackoverflow.com/questions/1136106/what-is-an-efficient-way-of-inserting-thousands-of-records-into-an-sqlite-table

반응형