[Django] ORM Lazy-Loading, N+1 문제

JinUk Lee·2024년 4월 16일
0

DRF 학습하기

목록 보기
51/57
post-custom-banner

Lazy-loading

Django ORM은 Lazy-loading 라는 특징을 가진다.

이 Lazy loading는 ORM에서 명령마다 DB에 접근해 데이터를 가져오는 방식이 아니고, 명령 처리가 끝나고 실제 데이터를 불러올때 쿼리문을 실행하는 방식이다.

person = Person.objects.all()

흔히 볼 수 있는 위 코드에서 db는 호출되지 않는다.

ps_list = list(person)

불러왔던 person을 list()에 넣었을때 쿼리를 실행하여 DB에 접근하고 데이터를 가져온다.

Query의 실행

명령처리가 끝나고 쿼리를 실행하다고 했는데, 정확하게는 특정 시점에서 쿼리를 실행한다.

이 특정 시점은 다음과 같다.

  • 슬라이싱
  • Pickling, Caching
  • repr(), len(), bool(), list()
  • for문

N+1 문제

이 Lazy-loading 에서는 N+1 문제라는 성능 문제가 발생한다.

N+1 문제란 외래키를 사용할때 발생하는 문제다.

예를 들어서 그룹에 몇개의 팀이 있고, 팀은 사람으로 구성되고 사람마다 각자 이름이 있다고 생각해보자.

우리는 이 사람들의 이름을 구하려고한다.


# 쿼리를 보내기 전
teams = Team.objects.all()

# 쿼리를 보내는 시점
for team in teams:
	print(team.person.name)

처음에 teams를 구할때는 쿼리를 날리지 않는다.

따라서 아래에서 team의 person 정보를 가져오기 위해서 반복횟수만큼 N번의 쿼리를 더 날리게 되는 것이 N+1 문제이다.

해결방법

N+1 문제를 해결하기 위해서는 Eager Loading 방식을 사용하는 것이다. Eager Loading는 관련된 데이터를 모두 한번에 가져오는 방식으로, 중복된 데이터를 제거하는데 도움을 준다.

여기서 사용되는 것이 select_related(), prefetch_related() 이다.

profile
개발자 지망생
post-custom-banner

0개의 댓글