본문 바로가기
프로그래밍/Django

[Django][Python]QuerySet을 통해 알아보는 ORM의 특징

by 우주를놀라게하자 2022. 4. 6.
반응형
SMALL

해당 정보는 Pycon자료를 통해 만들었습니다.

참고자료는 아래와 같습니다

[링크1], [링크2]

ORM이란?

ORM 설명

Object Relational Mapping, ORM은 객체 지향적인 방법으로 데이터를 쉽게 조작할 수 있게 해준다.
Model class를 통해 객체를 만들고, 이 객체를 통해 DB에 접근한다

[예시]

Django ORM은 2가지의 특징을 가진다.

1. Lazy Loading(지연로딩) : 필요한 시점에 SQL을 호출하는 특징

2. Lazy Fetching : 외래키로 접근할 때, 바로 접근(?)할 수 있는 특징을 가진다.

[Lazy Loading 특징 예시]

조금더 자세한 설명을 코드로 확인해 볼 수 있다.

아래는 위의 설명을 풀어놓기 위해서 내 프로젝트 내부의 코드이다.

class HomeView(ListView):

    context_object_name = 'cafes'

    @silk_profile()
    def get_context_data(self, **kwargs):

        cafe = Cafe.objects.all()

        if isinstance(cafe, QuerySet):
            print('cafe는 아직 쿼리셋이기 때문에 이 print문이 출력된다')

        cafe_list = list(cafe)
        if isinstance(cafe_list, QuerySet):
            print('cafe_list는 쿼리셋이 아니기 때문에, 이 print문이 출력안됨')



        # print(City.continent.objects.all())
        context = super().get_context_data(**kwargs)
        context["cityList"] = City.objects.all()
        return context

위와 같이 나의 프로젝트에서 테스트를 해본 결과 터미널상에서 cafe_list에 관한 정보는 print가 안되는 것을 확인 할 수있다. 이 말인 즉슨, ORM을 활용하여 객체를 선언한 순간에 데이터를 가져오는것이 아닌, 실제로는 list()를 통해서 묶은 순간에 query문이 실행한다는 특징을 가진다.

결론은 코드상에 내가 ORM만 선언한다 해서 모든 쿼리가 발생하는 것이 아니라, 선언한 ORM객체를 사용할 경우에만 쿼리가 발생한다는 것을 알 수 있다.

설명이 모호한것 같아서 원본 예시를 아래에 첨부해둔다.

다시 설명하자면, orders, companies라는 orm객체가 생성되었지만, 실제로는 list()로 묶은 users만 쿼리가 실행되었다는 예시다.

[Lazy Fecting의 특징 예시]

위의 예시를 분해해보면, book이란 모델의 타이틀에 묶인 외래키를 fetching하여 author의 ID값을 가져온다.

 

BUT 여기서 N+1문제가 발생할 수 있다!!

N+1 problem이란? 무엇인가?

Django를 활용하여 처리하면, 2가지 특성으로 인하여, Query문을 2번 사용하게 된다.

첫째줄을 확인하면, Book.object.all()에서 가져온 쿼리문을 For문으로 가져올때 첫 쿼리문이 발생하고, 외래키를 fetching하는 과정에서 2번의 문제가 생긴다. 이것을 N+1문제라고 한다

다음글은 N+1문제를 해결하는 방법에 대해서 정리할 예정이다.

반응형
LIST