#select_related() #prefetch_related()
Django ORM에서 사용되는 성능 최적화 기능들을 알아보자. 이와 관련해서 2가지 기능이 있는데, 이들 모두 관련된 객체를 미리 로딩(Eager Loading <-> Lazy Loading)하여 추가적인 쿼리를 방지한다.
목차
1. select_related()
2. prefetch_related()
DB에서 데이터를 가져올 때 연관된 것들도 가져와 lazy loading을 방지하여 N+1문제를 해결
fields를 매개변수로 사용 : 그래서 특정 인스턴스의 필드값을 바로 가져올 수 있는 것임
하나의 쿼리로 관련된 객체들을 가져오기 때문에 쿼리 수 감소
OTO(One-To-One : OneToOneField ), MTO(Many-To-One : ForeignKey)관계에서 주로 사용
작은 데이터셋에서 효과적
single-valued relationships(OTO(One-To-One), MTO(Many-To-One) 관계)에서만 사용가능하다. 이는to avoid the much larger result set that would result from joining across a 'many' relationship 때문이다.
실제 SQL문이 다음과 같이 변화한다.
creating an SQL join
including the fields of the related object in the SELECT statement
# models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
# views.py
from django.shortcuts import render
from .models import Book
def book_list(request):
books = Book.objects.select_related('author').all()
return render(request, 'book_list.html', {'books': books})
이렇게 하지 않으면
instance = Book.objects.all()
instance.author
로 2번 실행해야함
lookups를 매개변수로 사용
prefetch 말 그대로 설정한 값과 관련된 부분을 미리 가져와서 성능 향상
OTO(One-To-One), MTO(Many-To-One), MTO(Many-To-One), MTM(Many-To-Many) 관계에서 사용
대규모 데이터셋에서 효과적
# views.py
from django.shortcuts import render
from .models import Book
def book_list(request):
books = Book.objects.prefetch_related('author').all()
return render(request, 'book_list.html', {'books': books})
책들에 대한 쿼리를 실행하는 동안 author(관련된 저자)들도 함께 미리 가져와서 성능을 최적화하는 것이다.
공식문서 : https://docs.djangoproject.com/en/5.0/ref/models/querysets/#prefetch-related pdf p.1692, 1694