2010-08-03 5 views
31

저는 sqlite 백엔드에서 장고를 사용하고 있으며 쓰기 성능이 문제가됩니다. 나는 어떤 단계에서 "적절한"DB로 졸업 할 수도 있지만, 잠시 sqlite로 막혀있다. 필자의 필기 성능 문제는 아마도 많은 수의 행을 생성한다는 사실과 관련이 있으며 아마 save() 때마다 디스크에 DB를 잠그고 잠금을 해제하고 동기화 할 때라고 생각합니다.Django에서 save()를 집계 하시겠습니까?

많은 수의 save() 호출을 어떻게 단일 데이터베이스 작업으로 집계 할 수 있습니까?

+0

http://stackoverflow.com/questions/1136106/efficent-way-to-insert-thousands-of-records-into-a-table-sqlite-python-django –

+0

@Tomasz - 링크 해 주셔서 감사합니다. @commit_manually 데코레이터는 내가 필요한 성능 향상을 제공한다. 나는 다른 사람이 그것을 아주 잘 커버한다고 생각하기 때문에 폐쇄에 대한 나의 질문을 속죄 판으로 표시했다. – kdt

+0

실제로 폐쇄에 투표하는 대신 질문을 닫을 수 있습니다. –

답변

54

실제로 이것은 생각보다 쉽습니다. Django에서 transactions을 사용할 수 있습니다. 이러한 일괄 데이터베이스 작업 (특히 저장, 삽입 및 삭제)은 하나의 작업으로 수행됩니다. 가장 쉬운 방법은 commit_on_success입니다. 본질적으로 데이터베이스 저장 작업을 함수로 랩 한 다음 commit_on_success 데코레이터를 사용합니다.

from django.db.transaction import commit_on_success 

@commit_on_success 
def lot_of_saves(queryset): 
    for item in queryset: 
     modify_item(item) 
     item.save() 

이렇게하면 속도가 크게 향상됩니다. 또한 항목 중 하나라도 실패하면 롤백 기능을 활용할 수 있습니다. 수백만 개의 저장 작업이있는 경우 commit_manuallytransaction.commit()을 사용하여 블록으로 커밋해야하지만 거의 필요하지는 않습니다. 장고 1.6으로 도움이

희망,

+0

이것은 거의 마술 같았습니다. 많은 레코드를 생성하는 무작위 함수를 래핑했고 SQLite에서 즉시 몇 배 더 빨라졌습니다. – alberge

+32

이 답변을 통해 지금 실행중인 사용자에게는 'commit_on_success'가 사용되지 않습니다. 대신 새로운 버전 인 '원자'로 바꾸고 똑같은 마법 효과를 낼 것입니다! – Pterosaur

+7

'atomic' 참조 : https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.atomic – Paolo

1

"많은 수의 save() 호출을 어떻게 단일 데이터베이스 작업으로 집계 할 수 있습니까?"

필요하지 않습니다. Django는 이미 캐시를 관리합니다. 저장 기능을 사용하면 DB 캐싱을 향상시킬 수 없습니다.

수정 "쓰기 성능 문제는 아마 내가 많은 수의 행을 만드는거야 사실 관련이 있습니다."

SQLite는 꽤 느립니다. 즉,이 방법. 쿼리는 다른 대부분의 DB보다 빠릅니다. 글쓰기가 꽤 느립니다.

더 심각한 아키텍처 변경을 고려하십시오. 웹 트랜잭션 중에 행을로드합니까? 즉, 파일을 대량 업로드하고 해당 파일에서 DB를로드하는 중입니까?

웹 거래 내에서 대량로드를 수행하는 경우 중지하십시오. 당신은 더 똑똑한 것을 할 필요가 있습니다. celery을 사용하거나 다른 "일괄 처리"기능을 사용하여 백그라운드에서 부하를 처리하십시오.

웹 트랜잭션에서 파일 유효성 검사로 제한하고 사용자가 HTML 페이지를 기다리지 않을 때로드를 시도합니다.

+1

sqlite가 참으로 본질적으로 디스크를 사용하는 방식으로 인해 쓰기가 느려지더라도 * 이렇게 느릴 필요는 없습니다. 주석 기자가 제안한 것처럼 @commit_manually 데코레이터를 사용하기 시작하여 실제로 상당한 개선을 발견했습니다. – kdt

41

새로운 atomic, a simple API to control DB transactions입니다.워드 프로세서 그대로 복사 :

from django.db import transaction 

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

context manager A와 :

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.db.transaction 기능 autocommit(), commit_on_success()commit_manually()는 사용되지 않으며

원자는 decorator A와 모두 사용할 수있다 장고 1.8에서 제거됩니다.

관련 문제