Django ORM (QuerySet) 최적화

Joey Lee·2020년 12월 2일
3

Django

목록 보기
22/23
post-custom-banner

본 자료는 "Django ORM(QuerySet) 구조와 원리 그리고 최적화 전략"이라는 PyCon Korea 2020에서 김성렬님이 강의하신 내용을 요약 정리한 것입니다.

1. 목차

2. 쿼리셋을 통해 알아보는 ORM의 특징

1) Lazy Loading : 지연 호출

  • 정말 필요한 시점에 SQL를 호출한다.
  • 정말 필요해야만 SQL을 호출한다.
  • 정말 필요한 만큼만 호출한다.
    => 두 번 호출하지 않도록 주의해야 한다. 예제 3번 참고.

2) Caching

  • QuerySet 캐싱을 재사용해서 3번 케이스를 예방함

3) Eager Loading 즉시 로딩 : N+1 Problem

  • 쿼리셋은 Lazy Loading을 함. 하지만 SQL로 한 번에 여러 개의 데이터를 가져오고 싶을 때가 있는데 이게 Eager Loading이라고 하고, 이를 지원하기 위해 select_related, prefetch_related 메소드를 제공하고 있음.
  • Lazy Loading이기 때문에 정작 필요한 for문에서 계속 쿼리를 날려서 아래와 같이 N+1번 동일한 쿼리를 날릴 수 있음

3. 쿼리셋 상세

1) 쿼리셋 구성요소

  • 쿼리셋은 1개의 쿼리와 추가 쿼리로 구성된다.
  • 쿼리셋을 호출하고 나면, 그 자료는 캐시에 저장되고 이후에는 캐시에서 불러와서 사용한다. 만약 캐시에 데이터가 없다면 다시 쿼리를 날려서 데이터를 가져온다.
  • prefetch_related가 추가 쿼리에 해당한다. select_related는 추가 쿼리가 아님
  • select_related는 원래 쿼리에 조인을 통해서 데이터를 즉시 로딩하는 방식
  • prefetch_related는 추가 쿼리를 수행해서 데이터를 즉시 로딩하는 방식
  • 역참조 모델의 경우 select_related 옵션을 줄 수가 없음. 아래 예제에서는 상품의 경우는 select_related를 할 수가 없음. 하지만 그 반대는 가능함. order_owner는 prefetch_related는 가능함. 이건 장고의 제약 사항임
  • prefetch_related에 추가적인 조건절을 걸고 싶다면 prefetch 함수를 이용하면 됨. (select_related는 뒤에 그냥 filter를 걸면 됨)

3) 연습문제

4) SQL 퍼포먼스를 커버하는 Testcase [CaptureQueriesContext 활용]

4. 실수하기 쉬운 쿼리셋의 특성들

1) prefetch_related는 완전 별개다.

  • filter는 1개의 쿼리에 대해 이뤄진다. 따라서 추가적인 쿼리인 prefetch_related는 filter의 적용을 받지 않는다.
  • 아래와 같이 하면 불필요한 데이터를 더 검색하게 만드는 비효율적인 쿼리가 되어버림

2) 쿼리셋 작성 순서

  • Model -> annotate -> select_related -> filter -> prefetch_related

3) 재사용하지 못 하는 쿼리셋

4) RawQuerySet 사용하기

5) 서브쿼리 발생조건 : QuerySet in QuerySet

  • 속도 이슈 때문에 서브쿼리는 가급적 지양해야 함. 근데, 어떤 경우에 서브쿼리가 발생할까?
  • 서브쿼리가 되지 않도록 1개 쿼리가 다 실행되고 그 다음 쿼리가 될 수 있도록 해결해야 함.
profile
안녕하세요!
post-custom-banner

0개의 댓글