2019.09.24 django select_related, prefetch_related
문제의 제기
- 기본적으로 장고의 ORM은 불필요한 쿼리문을 많이 요청한다는 이야기가 많았다. 실제로 확인을 해보니 불필요한 중복 쿼리문이 너무 많이 사용되고 있었다.
- 디버그 툴바를 활용하면 불필요한 쿼리문의 요청들을 확인할 수 있다.
기본적으로 ORM에서는 하나의 모델을 바탕으로 Foreignkey가 묶인 다른 자료들도 불러서 사용할 수 있다.
- 문제는 여기서 발생하게 된다. 하나의 모델을 불러오고 또 그 관련된 Foreignkey가 연관된 자료들을 불러오려고 하면 DB에 접근을 2번이나 해야 한다.
- 그렇다면 하나의 모델을 불러올 때 미리 foreignkey로 연결된 자료까지 불러 올 수 있으면 어떨까? 그렇게 되면 DB에 접근을 한번만 해도 된다!
select_related와 prefetch_related란?
- select_related와 prefetch_related는 하나의 Queryset을 가져올 때, 미리 related objects들까지 다 불러와주는 함수이다.
- 비록 query를 복잡하게 만들지만, 불러온 데이터는 모두 cache에 남아있게 되므로 DB에 다시 접근해야 하는 이슈가 줄어들 수 있다.
- 2가지는 모두 DB에 접근하는 수를 줄여주어, performance를 줄여주지만 그 방식에는 차이가 있다.
select_related와 prefetch_related의 차이
- 와 위의 글을 읽고 머리를 딱 쳤다.
- select_related와 prefetch_related 모두 필요한 데이터들을 모두 한번에 가지고 올 수 있게 도와준다.
- select_related는 foreign-key 혹은 one-to-one과 같은 1:1 관계에서 사용이 가능하다.
- 그에 반해 prefetch_related의 경우 many to many, foreign-key 등 가리지 않고 사용이 가능하다.
- 하지만 실제로 해당 내용을 한번에 모두 가지고 오기 위해 호출해야 하는 횟수가 다르다.
- 결론부터 말하자면 prefetch_related가 더 많은 쿼리문(순차적으로 불러옴)을 실행해야 되는 반면에 select_related는 한번의 쿼리문으로 모든 것을 가지고 온다.
결론
- select_related와 prefetch_related를 적절하게 사용하면 제일 좋다 :)
확인 방법
- debug toolbar의 SQL문을 참고해보면 된다!