TIL - select related 와 prefetch_related

이태연·2022년 3월 15일
0
post-thumbnail

결론부터 말하자면

select_relatedprefetch_related 둘 다 하나의 Queryset을 가져올 때 미리 related objects 까지 다 불러와서 DB에 접근하는 빈도를 줄여주는 역할을 합니다.

하지만 당연하게도 차이점 또한 존재합니다.
이번 포스팅에서는 select_related와 prefetch_related가 각각 언제 사용이 되는지 그리고 차이점은 뭔지! 알아보도록 하겠습니다.

select_related는 1:1관계 그리고 1:N관계에서 N이 사용할 수 있습니다.

from django.db import models


class Owner(models.Model):
    name = models.CharField(max_length=20)

    class Meta:
			db_table = 'owner'


class Cat(models.Model):
    name = models.CharField(max_length=20)
    owner = models.ForeignKey(Owner)

    class Meta:
			db_table = 'cat'

위와 같은 모델구조에서 select_related를 사용한 경우와 사용하지 않은 경우를 비교해보자면

#1번코드
cat = Cat.objects.get(id=1)
owner = cat.owner
#2번코드
cat = Cat.objects.select_related('owner').get(id=1)
owner = cat.owner

1번코드는 select_related를 사용하지 않았고
2번코드는 select_related를 사용하였습니다.

1번의 경우 Cat모델에서 id에 맞는 데이터를 가지고 위해 1번, 그리고 그 cat의 owner를 찾기 위해 1번, 총 2번 DB에 접근해야합니다.

하지만 2번 코드의 경우는 한번에 id에 맞는 cat과 owner정보를 한번에 가져오기 때문에 DB에 총 1번만 접근하면 가능합니다.

prefetch_related의 경우 ManyTOMany관계에서 사용할 수 있고
1:N 관계에서 1이 사용할 수 있습니다.
위와 동일한 모델구조가 있다고 가정할 경우 owner가 cat을 가지고 오고 싶을때는 다음과 같이 사용할 수 있습니다.

owner = Owner.objects.prefetch_related('cat_set').get(id=1)

select_related와 prefetch_related 차이에는 join을 어디서 하느냐의 차이 역시 존재합니다.
select_related의 경우 DB에서 join 기능을 수행한 후 가져오기 때문에 한번의 쿼리로 가져올 수 있지만
prefetch_related의 경우 python으로 join을 하기 때문에
python에서 join 기능을 수행하므로 불러올 때 한번의 쿼리를 실행하고 불러온 후 한번의 쿼리를 더 실행하게 됩니다.

참고자료

https://blog.myungseokang.dev/posts/django-query-optimization/
https://codermun-log.tistory.com/179

profile
주니어 백엔드 웹 개발자입니다.

0개의 댓글