TIL51 | Django ORM 최적화(Lazy Loading, Caching, N+1 Problems)

2021. 11. 18. 08:35언어/Python

반응형

Lazy Loading(지연 로딩)

필요할 때만 함수를 호출하는 개념

  • 파이썬에서는 generator 함수
  • Django에서는 QuerySetAPI에서 지연로딩 특징을 가지고 있다.
# DB 호출되지 않음.

queryset = Publisher.objects.filter(id=20).exclude(id=2).annotate(count=Count('book'))

함수를 호출할 때 DB쪽에 실행되는 것이 아니라, queryset이 평가 될 때 DB를 호출한다.

QuerySet이 평가 될 때 == 실제로 db를 호출하는 시점

Slicing, Iteration, repr() print, len(), list(), bool(), ...

 

queryset = Publisher.objects.filter(id=20).exclude(id=2).annotate(count=Count('book'))

# Lazy Loading시 쿼리는 어디에 저장되어 있는가?
print("queryset.query에 저장된 SQL문 :: ", queryset.query)

QuerySet으로 반환하는 함수들을 실행할 때 queryset.query 변수에 Sql문이 저장된다.

 

Caching

지연로딩이 가지는 문제

같은 값을 가져오더라도 요청할 때마다 통신해야한다.

# 각각 select문으로 호출 (3번 호출)
queryset[0]
queryset[0]
queryset[0]

 

해결 방법

QuerySet이 가지는 caching 기능으로 위 문제를 해결할 수 있다.
result_cache에 db에서 가져온 값을 저장해둔다.

(caching을 하는 경우 : list, for문)

# 단 1번 select문으로 호출
list(queryset) ---> queryset.result_cache에 sql문으로 가져온 값들을 저장해둔다.

queryset[0]
queryset[0]
queryset[0]

 

N + 1 Problems

API 설계 방식 (Architecture)

  • REST
    • 엔드포인트가 여러개
    • 엔드포인트가 정의된 대로만 줄 수 있음
    • resource별로 http method로 uri를 설계하는 것
  • GrapQL
    • 엔드포인트 1개
    • 모든 요청을 한군데로 보낸다
    • Front에서 Back에 Sql문처럼 uri 요청을 보낸다.

 

select_related

queryset.query : 하나의 쿼리에 계속 더해진다.

 

prefetch_related

queryset.query에는 하나의 root query만.

queryset._prefetch_related_lookups : 추가 쿼리 개념. 기존 쿼리보내고, 추가적으로 다음 쿼리 보낸다.

prefetch_related('my_tables')는 전체 데이터를 가져와서 caching해두는 것이기 때문에,

역참조할 모델에 filter를 걸어야하는 경우 모든 데이터마다 where 조건을 걸어서 쿼리를 날리게 된다.

이런 문제를 해결하기 위해 Prefetch 객체를 사용할 수 있다.

total_books    = [book.name for book in store.books.all()]
filtered_books = [book.name for book in store.books.filter(name='Book9991')]


queryset = Store.objects.prefetch_related(
    Prefetch('books', queryset=Book.objects.all(), to_attr='total_books'),
    Prefetch('books', queryset=Book.objects.filter(name='book999'), to_attr='filterd_books'),
)

 

Prefetch 객체

  • 역참조 할때 filter 조건을 걸어야하는 경우에 사용

 

 

Load test

npm install loadtest

  • API 성능 테스트

 

반응형