select_related는 SQL Query 문의 JOIN을 사용하여 foreign-key(one to one, many to one)를 사용하여 정참조 할 때 사용하며 QuerySet을 가져올 때 미리 related objects까지 불러오는 함수이다.
select_related를 통해 불러온 data들은 데이터베이스 서버가 종료되기 전 까지 Cache에 남게되어 쿼리가 실행될때마다 DB에 접근하지 않게되어 처리속도가 향상된다.
위 테이블을 보시면 3명의 user들은 1개의 회사들과 OneToOne 관계로 연결되어 있습니다.
이때, 모든 user들의 쿼리셋을 가져온다면 일반적으로 MyUser.objects.all()
이렇게 사용할 수 있습니다.
이때 쿼리는 총 몇 개가 실행될까요??
정답은 총 4번의 쿼리입니다.
이제 그럼 MyUser.objects.all().select_related('company')
를 사용하여 Company 모델들까지 모두 가져와 보겠습니다.
이번에는 몇 개의 쿼리가 실행될까요?
정답은 1개입니다. 쿼리를 자세히 살펴보면
SELECT `user_myuser`.`id`, `user_myuser`.`password`, (중간 생략) `company_company`.`date_establish` FROM `user_myuser` INNER JOIN `company_company` ON (`user_myuser`.`company_id` = `company_company`.`id`) LIMIT 21; args=()
만약, MyUser에 100개의 company와 OneToOne 관계를 가지고 있는 100명의 User가 있다면
MyUser.objects.all()
을 사용할 때 101번의 쿼리를 MyUser.objects.all().select_related('company')
로 단 1개의 쿼리로 모든 데이터를 가져올 수 있겠죠?
prefetch_related는 쿼리셋을 반환할 때 foreign-key, OneTonOneFeild 관계뿐만 아니라 ManyToMany, ManyToOne 관계의 모델들 함께 가져오는 ORM이다.
prefetch_related는 select_related 와 비슷하지만 다릅니다. MyUser.objects.all().select_related('company')
을 사용하여 동일한 조건의 DB에서 쿼리셋을 가져와 보겠습니다.
이번에는 2개의 쿼리가 실행되었습니다. prefetch_related 는 select_related 의 차이를 아시겠나요?
select_related는 inner join으로 쿼리셋을 가져오고, prefetch_related는 myuser, company 에 대해 각각의 쿼리로 쿼리셋을 가져옵니다.