Eager Loading & Options in ORM

Min-Ho Lee·2020년 11월 20일
3

Learn Django

목록 보기
12/13

Fri_Nov_20
.
.
.
저번 글에서는 Lazy Loading과 Cache(Caching)에 대해 공부를 했다.

QuerySet은 기본적으로 Lazy Loading 방식을 선택한다.
하지만 SQL로 한 번에 많은 데이터를 가져오고 싶을 때가 있을 것이다.

이를 ORM에서 Eager Loading이라고 부른다.
Eager Loading은 즉시 로딩이라는 뜻이다.
QuerySet에서는 이를 지원하기 위해 select_related와 prefetch_related라는 메소드를 지원한다.

ORM을 잘 이해하지 못하면 N+1문제가 자주 발생하게 된다.

예를 들어보자.
현재 ERD의 상황은 user와 userinfo라는 테이블이 1:1 관계에 있다.

users = User.objects.all()

for user in users:
    user.userinfo

이렇게 모든 유저의 정보를 가져온 후, 1:1관계인 userinfo의 정보를 가져온다고 가정하자.
여기서 바로 N+1의 문제가 발생하는 것이다.

현재 users라는 QuerySet에는 모든 user의 내용이 담겨있지만, userinfo의 내용이 담겨있진 않다.
그래서 user는 QuerySet에서 'userinfo의 데이터가 없네?'라고 생각해서 SQL을 다시 호출하게 된다.

이것이 왜 N+1문제라고 부르냐 하면, 만약 모든 유저의 정보가 100명이었다면, 처음에 모든 유저의 정보를 가져오는 쿼리 1번, 그리고 for 문을 돌며 100번의 추가 쿼리가 더 발생하게 된다.

만약 유저의 정보가 1000명이었다면 1000+1번.
그래서 N+1문제라고 부르는 것이다.
이것이 Lazy Loading으로 인해 발생하는 대표적인 문제이다.

그렇다면 어떻게 해결해야 할까?

바로 즉시 로딩을하는 방법인 Eager Loading전략을 택하도록 QuerySet에 옵션을 주어야 한다.

바로 아래에서 이어서 다루겠다.

QuerySet의 구성요소

QuerySet은 다음과 같이 이루어져 있다.

❗️QuerySet은 1개의 쿼리와 0~N개의 추가쿼리로 이루어져 있다.

내가 이해한대로 쉽게 풀어쓰자면
QuerySet += Query인 것이다.
(TMI이지만 보통 이 Query를 메인 쿼리라고 부르는것 같다.)

QuerySet class에는 많은 것이 있지만, 그 중에서 3개(?) 정도만 알고있으면 될 것 같다.

_result_cache

QuerySet의 캐싱된 정보가 여기에 담겨있다.
여기에 없다면 추가로 SQL 문을 호출하는 것이다.

추가 QuerySet이 될 타켓들을 지정해 놓는곳이다.

_iterable_class

QuerySet의 반환 타입을 무엇으로 할건지 지정해주는 놈이다.
Default로는 일반적으로 Django Model을 반환한다.
values라고 하면 dict형태로,
values_list라고 하면 tuple list의 형태로 데이터 값을 반환하게 된다.

Django QuerySet Class
위 링크로 가면 코드가 자세히 나와있다.

profile
🐇 Rabbit can take a rest, but 🐢 turtle can't

0개의 댓글