logo
Published on

Django select_related 의 활용법

Authors

TL;DR

SQL 만 사용하다 ORM 을 사용하게 되면 처음에는 깔끔한 모델 정리와, 테이블 생성부터 관리까지 편리한 기능들에 만족하게 된다. 하지만, 조금 복잡한 쿼리가 필요한 경우 ORM 별로 사용법이 달라 찾아보게 된다. 금번 포스트 에서는 특히 헷갈리기 쉬운 select_relatedprefetch_related 를 살펴보고자 한다.

select_related

Django documentation 에서의 원문은 select_related 를 아래와 같이 설명하고 있다. 간단하게 요약해 보자면 쿼리 시 Foreign Key 관계에 있는 데이터를 가져올 수 있다는 것이다. Foreign Key 관계의 데이터가 필요할 때 여러번 쿼리할 필요가 없다고 이야기 한다. 사실상 Join 의 활용과 비슷한 이야기 이다.

Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query. This is a performance booster which results in a single more complex query but means later use of foreign-key relationships won’t require database queries.

예시를 통해 자세히 알아보자. Entry 모델은 Blog 모델과 Foreign Key 관계이다. Entry 모델의 blog 데이터를 불러오기 위해 Entry select 1회, entry queryset 에서 blog 호출 2회 까지 해서 총 두번의 쿼리를 실행하게 된다.

# Hits the database.
e = Entry.objects.get(id=5)

# Hits the database again to get the related Blog object.
b = e.blog`

하지만 select_related 를 사용할 경우 get 을 통해 생성된 queryset 을 통해 추가 쿼리 없이 데이터를 얻을 수 있어 성능을 개선할 수 있다. 그렇다면 select_related 는 실제 쿼리로 어떻게 번역될까?

# Hits the database.
e = Entry.objects.select_related("blog").get(id=5)

# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog

위 코드는 Author, Publisher 두 Foreign Key 관계의 모델에서 데이터를 추출하는 예시 이다. authors queryset 을 통해 publisher 의 데이터 까지 추가 쿼리 없이 조회할 수 있다.

authors = Author.objects.select_related('publisher').filter(name='John')

이는 SQL 로 표현하면 아래와 같다. Inner Join 을 사용한 예시 이다.

SELECT * FROM author
INNER JOIN publisher ON author.publisher_id = publisher.id
WHERE author.name = 'John';