728x90
반응형
Forign Key 참조를 사용해보다가 발견한 현상
아래 두 모델은 DRF를 익히기 위해 만든 모델이다
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
password = models.CharField(max_length=128)
objects = UserManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
class Feed(models.Model):
id = models.BigAutoField(help_text='Feed ID', primary_key=True)
user_id = models.ForeignKey("User", on_delete=models.CASCADE, db_column='user_id')
title = models.TextField(help_text='Feed title', null=False)
content = models.TextField(help_text='Feed Content', blank=True, null=True)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
각 Field에 대한 설명은 생략하겠다. 이 글의 목적에 맞게 Feed라는 모델이 User모델의 기본키를 참조(model.ForignKey("User"...) 하고 있는 걸 볼 수 있다. 겉으론 봐선 이상이 없어 보인다 문제는 다음과 같은 code를 쓸 때 나타났다.
class FeedService(serializers.ModelSerializer):
class Meta:
model = Feed
fields = ['title', 'content']
@classmethod
def read(cls):
query_result = Feed.objects.all()
data = [
{
'id': query.id,
'user_pk': query.user_id.pk,
'title': query.title,
'content': query.content,
'create_at': query.create_at.strftime("%Y-%d-%m, %H:%M:%S"),
'update_at': query.update_at.strftime("%Y-%d-%m, %H:%M:%S")
} for query in query_result
]
return data
반환 데이터를 보면 단순히 Feed 라는 모델의 데이터를 뽑아서 Return 해주고 있는 모습을 볼 수 있다. 하지만 DJango의 SQL 로그를 찍어보면 다음과 같이 같은 쿼리가 여러 번 발생한다.
feed 테이블에는 query가 한 번만 발생하는 반면 참조하는 user 테이블에는 쿼리가 여러번 발생한다 정확히는 feed 테이블에 있는 데이터의 수만큼 발생하는 것이다.
정확한 해결법은 모르지만 아마 다음과 같은 해결법이 존재할 것이다.
1. Forign Key 대신 user_pk를 feed 테이블에도 선언한 뒤 외래키 참조가 아니라 연관성만을 갖도록 설정
2. Django나 DRF에서 제공해주는 직렬화 라이브러리를 찾아서 적용
위의 예제는 간단한 쿼리여서 눈에 띄는 현상이 발생하지만 않지만 같은 쿼리가 여러 번 발생한다는 것은 DB에 부하가 갈 수 있을 뿐만 아니라 비효율적으로 돌아간다는 대표적인 예이고 의도하지 않은 동작이므로 고치는 것이 좋지 않을까?
728x90
반응형
'Frame Work > Django' 카테고리의 다른 글
[Django] model migration 꼬였을 때 (0) | 2021.09.18 |
---|---|
[Django] app의 model만 관리하는 app을 만들어보자 (3) | 2021.09.16 |
django, timezone에 관한.. (0) | 2021.08.14 |
django.db.utils.DataError: (1366, "Incorrect string value: ~~~) (0) | 2021.04.28 |
django.db.utils.OperationalError: (1060, "Duplicate column name) (0) | 2021.04.27 |