쿼리셋은 Lazy Loading으로 동작한다.
하지만 한 번에 많은 데이터를 조회하고 싶을 때가 있는데
이것을 Eager Loading이라고 부르며 이를 지원하기 위해
select_related, prefetch_related 등이 있다.
- Lazy Loading이기 때문에 반복문 안에서
동일한 쿼리가 중복으로 발생하여 아래와 같이 N+1 문제가 발생할 수 있다.
쿼리에 JOIN하여 데이터를 즉시 로딩하는 방식
추가 쿼리를 수행하고 파이썬 레벨에서 JOIN하여 데이터를 즉시 로딩하는 방식
filter()는 1개의 쿼리에 대해 이뤄진다.
따라서 추가적인 쿼리인 prefetch_related는 filter의 적용을 받지 않는다고 한다.
아래처럼 할 경우, 데이터 조회를 위해 비효율적인 쿼리가 작성된다.
filter()안에서INNER JOIN으로 관계형 테이블을 조인한다.
그 이후 prefetch_related로 인해 추가 쿼리가 수행된다.
- prefetch_related 제거!
- INNER JOIN으로 데이터를 가져오도록 한다.
- filter안에 있는 관계형 조건을 Prefetch로 이동
- 이 방법은 user 쿼리에서 INNER JOIN을 하지않고
추가 쿼리에서 where절이 수정된다.
Model -> annotate -> select_related -> filter -> prefetch_related