FrameWork/Django

select_related와 prefetch_related

JHeaon 2024. 7. 10. 11:07

 

오늘은 select_related와 prefetch_related에 대해서 정리해보고자 한다. 해당 주제를 다루기 전에 Django의 ORM 특징과 쿼리 셋에 대해서 알고 가면 좀 더 이해에 도움이 된다.

 

https://jheaon.tistory.com/274

 

Django ORM과 QuerySet

오늘은 Django의 ORM과 QuerySet에 대해 알아보고자 한다. Django ORM과 QuerySetORM (Object Relational Mapping)ORM이란 Object Relational Mapping의 약자로 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해 주

jheaon.tistory.com

 


 

정참조, 역참조

일단 설명하기전에, 다음과 같이 모델이 정의되어 있다고 가정한다. 

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=20)
    contents = models.TextField()
    
class Comment(models.Model):
    contents = models.TextField()
    post = models.ForienKey("Post", on_delete=models.CASCADE)

 

 

  • 정참조

해당 객체가 다른 객체의 ForeignKey을 가지고 있거나, 1:1 관계인 상황에서 참조하는 경우를 정참조라고 한다. 현재 정의된 모델 기준에서는 코멘트에서 포스트로 접근할 때를 "정참조"라고 한다.

comment = Comment.objects.get(id=1)
post_title = comment.post.title # 정참조

 

 

 

  • 역참조

다른 객체가 ForeignKey를 가지고 있거나, M:N인 관계인 상황에서 해당 객체를 잠조하고 있는 다른 객체를 참조하는 경우를 역참조라고 한다. 현재 정의된 모델 기준에서는 포스트에서 코멘트를 참조할 때를 "역참조"라고 한다.

 

기본적으로 역참조되어 있는 모델에 접근할 때에는 '소문자모델명_set'으로 접근한다.

post = Post.obejcts.first()
comments = post.comment_set.all() # 역참조

 

 

 

 

 

 

 

select_related와 prefetch_related

  • select_related()

객체가 foreign-key(OneToOne, OneToMany)를 사용해 정참조를 할 시, 쿼리셋을 가져올 때 연관되어 있는 테이블까지 미리 가져오는 함수이다. 쿼리문에서는 INNER JOIN을 통해 쿼리가 수행된다.

 

comments = Comment.objects.select_related("post")

for comment in comments:
     comment.post
 
"""
SELECT "mall_comment"."id", "mall_comment"."contents", "mall_comment"."post_id", "mall_post"."id", "mall_post"."title", "mall_post"."contents" 
FROM "mall_comment" 
INNER JOIN "mall_post" ON ("mall_comment"."post_id" = "mall_post"."id"); args=(); alias=default

<Post: Post object (1)>
<Post: Post object (1)>
<Post: Post object (2)>
<Post: Post object (3)>
<Post: Post object (1)>
<Post: Post object (1)>
"""

 

 

 

  • prefetch_related()

객체가 정참조(ManyToMany, OneToMany)이거나 또는 역참조를 할 시, 연관되어 있는 테이블까지 미리 가져오는 함수이다. 쿼리문에서는 각 관계별로 데이터베이스 쿼리를 수행하고 파이썬 단에서 조인이 수행된다. 

 

posts = Post.objects.prefetch_related("comment_set")
for post in posts:
    post.comment_set

"""
SELECT "mall_post"."id", "mall_post"."title", "mall_post"."contents" 
FROM "mall_post"; args=(); alias=default

SELECT "mall_comment"."id", "mall_comment"."contents", "mall_comment"."post_id" 
FROM "mall_comment" 
WHERE "mall_comment"."post_id" IN (1, 2, 3); args=(1, 2, 3); alias=default

<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x103b699d0>
<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x103ece850>
<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x103b699d0>
"""

 

 

 

'FrameWork > Django' 카테고리의 다른 글

Django에서 static, media 관리하기  (0) 2024.07.29
N + 1 쿼리 문제  (0) 2024.07.10
orm과 queryset  (0) 2024.07.10
django-seed을 통해 더미데이터 만들기  (0) 2023.12.13
settings.py 분리하여 관리하기  (1) 2023.11.23

'FrameWork/Django'의 다른글

  • 현재글 select_related와 prefetch_related

관련글