django) defer, only 유용하면서 위험한 녀석들

렁호·2022년 5월 16일
0
post-thumbnail

defer, only

모델의 여러 필드 중 내가 원하는 필드만을 가져오는 ORM에 대해서 알아보자.

only

only의 경우 해당 모델에서 지정해주는 필드만을 가져오는 ORM이다.

values_list(<'field'>) 와 비슷해 보이지만 여러 차이가 있다.

Student.objects.all().only('name')
<QuerySet [<Student: Student object (1)>, <Student: Student object (2)>, <Student: Student object (3)>, <Student: Student object (4)>]>
Student.objects.all().values_list('name',flat=True)
<QuerySet ['윤정호', '김민수', '홍길동', '최수지']>

이렇게만 봐서는 똑같이 qeuryset을 반환하였기 때문에 무슨 차이인지 알기 힘들다.

오브젝트의 호출하였을 때 확실히 차이를 느낄 수 있다.

only_qs = Student.objects.all().only('name')
only_qs[0]
<Student: Student object (1)>
values_list_qs = Student.objects.all().values_list('name',flat=True)
values_list_qs[0]
'윤정호'

SQL 쿼리를 확인해보면 다음과 같은 차이가 있다.

# only 
SELECT "study_student"."id",
       "study_student"."name"
  FROM "study_student"
 LIMIT 1

#values_list
SELECT "study_student"."name"
  FROM "study_student"
 LIMIT 1

쿼리를 통해 알 수 있듯이 only를 사용했을 때는 해당 모델의 id까지 함께 가져온다.

활용법

두 ORM 모두 원하는 칼럼에 대해서만 쿼리를 날리기 때문에 쿼리 비용이 절약 된다는 장점이 있다.

다음의 예시를 보자

# values_list를 사용할 경우
name_list = list(Student.objects.all().values_list('name',flat=True))
do_something(name_list)

## only를 사용할 경우
only_qs = Student.objects.all().only('name')
name_list = [qs.name for qs in only_qs]
do_something(name_list)

뭐 스타일마다 다르겠지만 나의 경우 전자의 코드를 선호한다.

특정 값을 조회하여 사용하는 경우는 values_list가 좀 섹시한 느낌이다.

" 왜 only를 사용해야 하는가 " 하는 의문이 생긴다.

하지만 !! 조회가 아닌 수정이라면 ..!?

애초에 values_list는 특정 필드의 값을 반환하기 때문에 objects로서 역할을 수행할 수 없다.

하지만 only의 경우 해당 필드만을 가지고 있는 모델 오브젝트를 반환한다.

이게 무슨 의미인지 일반적인 ORM을 사용했을 때의 쿼리와 비교해보자.

# only
student = Student.objects.only('name').get(pk=1)
student.name = '렁호'
student.save()
#select query
SELECT "study_student"."id",
       "study_student"."name"
  FROM "study_student"
 WHERE "study_student"."id" = 1

#update query
UPDATE "study_student"
   SET "name" = '렁호'
 WHERE "study_student"."id" = 1

# general
student = Student.objects.get(pk=1)
student.name = '렁호'
student.save()
#select query
SELECT "study_student"."id",
       "study_student"."name",
       "study_student"."major",
       "study_student"."age",
       "study_student"."is_woman"
  FROM "study_student"
 WHERE "study_student"."id" = 1

#update query
UPDATE "study_student"
   SET "name" = '렁호',
       "major" = 'programming',
       "age" = 28,
       "is_woman" = 0
 WHERE "study_student"."id" = 1

이렇듯 only도 목적에 맞게 잘 사용한다면 충분히 섹시한 ORM으로서 사용이 가능하다.

defer

defer의 경우 only의 정반대이다 인자로 들어온 필드를 제외한 모든 필드의 값을 가져온다.

주의 사항

only, defer 모두 특정 필드에 대한 값을 가진 오브젝트이기 때문에 제외된 필드에 대해서 조회가 가능은 하지만 해당 필드를 조회하기 위해 쿼리가 한 번 더 날라가게 된다.

그러므로 꼭 로직상 특정 필드에 대한 접근만이 확실할 때 사용하자,

쿼리문 조금 줄일라다가 DB 커넥션이 두 배로 늘어나는 마법이 생길 수도 있으니 절대 주의해야 한다.

profile
식욕, 수면욕, 성욕 만땅

0개의 댓글