select_related
와 prefetch_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