Django ORM 쿼리 최적화
Django ORM은 데이터베이스 작업을 쉽게 만들어 줍니다. 하지만 그 이면에는 위험이 숨어 있습니다. 연관된 객체를 잘못 가져오면 N+1 쿼리 문제가 발생합니다.
이는 100개의 포스트를 가져올 때, 앱이 101번의 쿼리를 실행할 수도 있음을 의미합니다. 이는 앱의 성능을 급격히 저하시킵니다.
이를 해결하기 위해 다음 두 가지 도구를 사용하세요:
select_related
ForeignKey와 OneToOneField에 사용하세요.
SQL JOIN을 사용합니다. 단 한 번의 쿼리로 연관 데이터를 가져옵니다.
- 예시: Post는 하나의 Author를 가집니다.
- 비효율적인 방식: 100개의 포스트에 대해 101번의 쿼리 실행.
- 최적화된 방식:
.select_related("author")를 사용하여 1번의 쿼리로 실행.
prefetch_related
ManyToManyField와 역방향 ForeignKey에 사용하세요.
별도의 쿼리를 실행한 뒤 Python에서 이를 결합합니다.
- 예시: Post는 여러 개의 Tags를 가집니다.
- 비효율적인 방식: 포스트를 위한 1번의 쿼리 + 각 포스트의 태그를 위한 쿼리가 매번 실행됨.
- 최적화된 방식:
.prefetch_related("tags")를 사용하여 총 2번의 쿼리로 실행.
전문가 팁:
- 루프에 진입하기 전에
Prefetch객체를 사용하여 연관 데이터를 필터링하세요. - 이들을 체이닝(chaining)할 수 있습니다. 하나의
queryset에서 두 가지를 모두 사용하여 작성자와 태그를 한 번에 가져올 수 있습니다. - 루프 내부에서 이미
prefetch된 관계에.filter()를 호출하지 마세요. 이는 캐시를 우회하여 데이터베이스에 다시 접근하게 만듭니다. select_related와 함께.only()를 사용하여 필요한 컬럼만 가져오세요.
요약:
- ForeignKey / OneToOne:
select_related사용. - ManyToMany / 역방향 FK:
prefetch_related사용.
django-debug-toolbar를 사용하여 쿼리 횟수를 확인하고 이러한 문제를 조기에 발견하세요.