오늘은 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 |