728x90
반응형
개요
Django ORM에서 참조 관계에 있는 모델 간에 데이터를 가져오게 될 때 사용하는 select_related & prefetch_related가 무엇인지 조사해봤다.
Model
이 포스팅에서 사용할 모델은 다음과 같다.
from django.db import models
class Machine(models.Model):
name = models.CharField(max_length=120)
class History(models.Model):
# 객체 이름을 참조할 떄는 string으로 circular import 방지를 위해
machine = models.ForeignKey("Machine", related_name="history_set", on_delete=models.CASCADE)
objects = models.Manager()
조사하다가 알게 된 사실인데 ForeignKey를 사용할 때 모델을 명시해주는 부분에 String으로 선언되있는 이유는 Comment에도 적어놨듯 Circular import를 방지하기 위해서다. 이 방법은 Django Guide를 읽다가 발견했는데 링크는 추후에 첨부해야겠다.
Select Related?
Selected Related는 정방향 참조, 정참조 라고 부른다. 내가 참조하는 table에 접근한다 라고 정의할 수 있는데 위의 Model을 예로 들었을 때, History 모델의 `machine`이라는 속성이 ForeignKey로 연결된 Machine의 데이터를 가져오는 경우이다.
즉, 1:N의 관계에서 N쪽에 있는 곳이 사용할 수 있다. Django ORM의 코드는 다음과 같이 생겨먹었다.
history = History.objects.select_related('machine')
위 구문이 실행하는 SQL을 보게 되면 다음과 같다.
SELECT `app_history`.`id`,
`app_history`.`machine_id`,
`app_machine`.`id`,
`app_machine`.`name`
FROM `app_history`
INNER JOIN `app_machine` ON (`app_history`.`machine_id` = `app_machine`.`id`)
LIMIT 21
DB에서 Join을 한 결과를 가져오고 Prefetch와 비교해보면 쿼리가 1번만 발생한다는 점도 알 수 있다.
Prefetch Related?
Prefetch Related는 역방향 참조, 역참조라고 부른다. 나를 참조하는 table에 접근한다라고 정의할 수 있는데 위의 Model을 예로 들었을 때 Machine 모델에서 자기를 참조하고 있는 History 모델의 데이터를 가져오는 경우이다.
즉 1:N의 관계에서 1쪽에 있는 곳이 사용할 수 있다. Django ORM 코드는 다음과 같이 생겨먹었다.
machine_qs = Machine.objects.prefetch_related('history_set').all()
위 구문이 실행하는 SQL을 보게 되면 다음과 같다.
(0.005) | SELECT `app_machine`.`id`,
| `app_machine`.`name`
| FROM `app_machine`
(0.012) | SELECT `app_history`.`id`,
| `app_history`.`machine_id`
| FROM `app_history`
| WHERE `app_history`.`machine_id` IN (1,
| 301,
| 302,
| 303)
쿼리가 2번 발생하는 것을 알 수 있다. 즉 Python에서 join 기능을 수행한다.
728x90
반응형
'Frame Work > Django' 카테고리의 다른 글
django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint') (0) | 2022.05.07 |
---|---|
[Django] Session ! (0) | 2022.05.06 |
[Django] model 필드 순서 조정하기 (0) | 2021.09.18 |
[Django] model migration 꼬였을 때 (0) | 2021.09.18 |
[Django] app의 model만 관리하는 app을 만들어보자 (3) | 2021.09.16 |