Lazy Loading(지연 로딩): 정말 필요한 시점에 SQL을 호출한다. / ORM의 기본적인 전략
쿼리셋 캐싱 : User[0] 을 부르고 User(all)을 부르면 쿼리를 두번 호출하지만 순서를 바꿔줌으로써 쿼리를 한번 만 호출
Eager Loading : 한번에 많은 데이터를 가져오기 쿼리셋에서는 selected_related, prefetch_related라는 메소드를 제공
N+1 Problem 이라는 대표적인 ORM에서 레이지 로딩을 발생하는 문제
(for user in users처럼 users 수만큼 쿼리를 호출해야할 때)
그래서 이런 케이스는 Eager Loading이라는 전략을 취하게 쿼리셋에 옵션을 줘야함
Eager Loading 옵션으로 쓰는
.selectedrelated('정방향참조필드') # 해당 필드를 join해서 가져온다
.prefetchrelated('역방향참조_필드') # 해당 필드는 추가쿼리로 가져온다
prefetch_related가 추가쿼리로 가져오는 점에서 쿼리셋 작성 순서는
filter(~=~).prefetch_related()를 권장한다.
위에서 유저 프로필들을 EagerLoading했다 쳤을 때 / (이거는 장고에서 이렇게 설계해놓은 듯)
User.user_porfile.all() # 여기서는 result_cache를 재사용
User.user_porfile.filter(hobby="여행") # 여기서는 쿼리가 발생
그래서 쿼리를 한번 더 발생시키지않고 캐시를 사용하려면
user_pofile_list = [profile for profile in User.user_porfile.all() if user_porfile.hobby="여행"]
이런식으로 .all()로 캐시를 사용해서 불러오게하면서 조건을 붙이면 해결가능하다.
서브쿼리 발생 조건들
values(), values_list() 이용 시 EagerLoading 옵션(selected_related,prefetch_related) 무시하고 조인해서 가져옴
values(), values_list() 안에 필요한 정보를 담아야 호출 가능
로직을 작성할 때 단조로운 SQL 작업을 줄여주고 Object와 Relational을 Mapping 해주는 장점이 있다.
하지만, 복잡성이 올라가면 NativeSQL을 쓰는 것도 좋다고한다. 때로는 가독성이 속도보다 중요할 때가 있다. 더구나 팀프로젝트라면 팀적으로 쿼리셋에 대한 이해를 같이 가져가야하는데 이러한 부분에서 속도만 고집하기보다는 편의성 등 효율성을 추구하는 게 중요하다고 본다.
이러한 점에서 DRF와 Pydantic에 대한 개념도 추가로 정리하고 싶다.
ORM이라서 쿼리셋이 캐싱이 되는거임?? (아니면 이것은 장고 ORM의 특징인가요??)
장고 ORM이 파이썬 언어로 편하게 db 연결해주는 거라고 보면 되는지?
장고 ORM을 쓰는 이유?? (장고 기본 값이라고 이해해야함?? MTV 모델에서 db에 접근하기 위한?)
장고는 object.all() 이런 걸 쓰니까 무조건 ORM을 쓴다고 봐도 되는지?
쿼리문 object와 objects의 차이점??
참고자료 : https://github.com/KimSoungRyoul/Django_ORM_pratice_project