select-related, prefetch-related

김회민·2022년 4월 18일
0

QuerySet API reference | Django documentation | Django

이게 뭐하는거임?

The only reason to use either of these methods is when a single large query is preferable to many small queries. Django uses the large query to create models in memory preemptively rather than performing on demand queries against the database.

related함수를 사용하는 이유는 하나의 큰 쿼리가 작은 쿼리보다 더 성능이 좋기 때문이다.

Django는 DB에 쿼리를 보낼때 주문형 쿼리를 수행하는 대신, 메모리에 모델을 미리 만들기 위해 큰 쿼리를 사용한다.

셀렉트할 객체가 역참조하는 single object(one-to-one or many-to-one)이거나, 정참조 foreign key 일 때 사용한다.

각각의 lookup마다 SQL의 JOIN을 실행하여 테이블의 일부를 가져오고, select .. from 에서 관련된 필드들을 가져온다.

from drink.models import *

drink = Drink.objects.get(id=1) 🎯
Category.objects.filter(id = drink.category.category_id) 🎯

drink_sr = Drink.objects.select_related('category').get(id=1) 🎯
drink_sr.category.name

Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.

구하려는 객체가 정참조 multiple objects(many-to-many or one-to-many)이거나, 또는 역참조 Foreign Key일때 사용한다.

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python.

prefetch-related는 따로따로 query를 날린 후 python에서 합친다.

from drink.models import *

drink_pr = Category.objects.filter(id=1).prefetch_related("drink_set") 🎯
Category.objects.filter(id = drink.category.category_id) 🎯

drink_sr = Drink.objects.select_related('category').get(id=1) 🎯
drink_sr.category.name

Understanding ForeignKey

parent&child의 관계를 생각하면 이해하기가 한층 쉬워진다.

  • ForeignKey는 child에 지정하는것이 좋다.
  • many-to-many관계에서 ForeignKey는 lower level에 지정하는 것이 좋다.
  • ForeignKey를 가진 child는 lookup(__)을 사용하여, parent의 필드를 참조할 수 있다.
>>> Drink.objects.filter(sub_category__name='cold brew')
<QuerySet [<Drink: dolce cold brew>, <Drink: cold brew>]>
  • parent도 같은 방법으로 자신의 child의 필드를 참조할 수 있다.
    • 이때, child class의 이름은 lowercase로 작성하자.
>>> SubCategory.objects.filter(drink__calories__gt=300)
<QuerySet [<SubCategory: cold brew>, <SubCategory: cold brew>]>

ForeignKey와 정참조와 역참조

  • FK를 가진 클래스에서 가지지 않는 클래스를 참조할 때는 정참조
  • FK를 가지지 않은 클래스에서 가진 클래스를 참조할 때는 역참조
class ModelA(models.Model):
    pass

class ModelB(models.Model):
    a = ForeignKey(ModelA)

ModelB.objects.select_related('a').all() # Forward ForeignKey relationship
ModelA.objects.prefetch_related('modelb_set').all() # Reverse ForeignKey relationship
profile
백엔드 개발자 지망생

0개의 댓글