Django ORM 최적화

BY Jung·2022년 1월 16일
0

QuerySet API의 특징과 동작원리
API가 부하를 받았을 때성능을 향상시키는 방법

select_related, prefetch_related로 N+1 문제를 해결

Lazy Loading(지연 로딩)

프로그래밍 전반적으로 있는 개념(장고에만 있지 않음)
함수를 호출했다고 해서 바로 응답하는 것이 아닌, 필요한 때에 값을 리턴해 줌

queryset = Publisher.objects.all()
all 함수를 실행해도 쿼리를 호출하지 않는다.
실제로 queryset은 query라는 속성 안에 SQL문을 저장해놓는다.

queryset2 = queryset.exclude(id=2).annotate(count=Count('book'))
queryset2도 마찬가지로 queryset에 계속 chainning하여 SQL문을 저장한다.

실제로 db를 호출하는 시점은
slicing, iteration, repr(), len(), list(), book()... 등을 사용했을 때이다

원하는 색깔을 얻기 위해 파레트에 주어진 물감을 섞어두었다가 도화지에 칠하는 느낌..?

Caching(캐싱)

list(queryset2)
queryset2[0]
queryset2[0]
queryset2[0]
의 코드는 사실 db를 1번만 호출한다

why? 장고의 내부적 기능인 "캐싱"이기 때문

for문을 돌리고 난 뒤에는 장고가 db를 호출하면서 _result_cache에 저장해서 그 결과를 활용하는 것을 볼 수 있다.
추가로 len(), list() 등등의 경우처럼 쿼리셋이 평가될 때 캐싱을 활용할 수 있다.

반대로
queryset2[0]
queryset2[0]
queryset2[0]
list(queryset2)
위의 코드는 db를 4번 호출한다

N+1 Problems(정참조)

queryset=Book.objects.all()
books =[]
for book in queryset:
books.append({
'id': book.id,
'name': book.name,
'publisher': book.publisher.name
})

해결방법

queryset = Book.objects.all().select_related("publisher")
books = []
for book in queryset:

정참조 관계에 있는 데이터는 select_related를 활용하자

N+1 Problems(역참조)

queryset=Store.objects.all()
stores =[]
for store in queryset:
stores.append({
'id': store.id,
'name': store.name,
'books': book
})

해결방법

queryset = Store.objects.all().prefetch_related("books")

profile
Slow and steady wins the race

0개의 댓글