정의
- DB Table간 연관 관계에서 발생하는 이슈이며, 1번의 쿼리 실행으로 N개의 데이터를 조회했는데, 원하는 특정 데이터를 위해 이 N개의 데이터 수만큼 반복해서 N번의 2차 쿼리 실행이 발생하는 문제
원인
- 근본적 원인은 ORM의 Lazy Loading
**Lazy Loading : ORM에서 매번 명령 실행시 DB에 접근해서 데이터를 불러오는게 아니라 모든 명령이 처리되고 실제 데이터를 불러와야 할 때 Query문이 실행되는 방식해결책
- Lazy Loading이 아닌 Eager Loading을 위한 ORM 명령어 사용하기
**Eager Loading : 미리 불러오고 싶은 데이터를 포함하여 쿼리를 날려 비효율적이게 발생하는 N+1 쿼리 이슈를 사전에 방지할 수 있는 방식. 또한 한 번 불러온 데이터는 local data cache에 보관하여 재사용하기에 효율적
- Eager Loading을 위한 2가지 방법
- selected_related : SQL Join과 같은 쿼리 역할 수행하며, single-valued 관계에서만 사용 가능
- prefetch_related : SQL WHERE-in과 같은 쿼리 역할 수행하며, 모든 관계에서 사용 가능
books = books.objects.all() # SELECT books.id, books.title FROM books for book in books: print(book.writer.name) # SELECT writers.id, writers.name FROM writers WHERE id = n
- 1번의 쿼리 실행으로 books의 모든 rows를 조회 후,
N번의 쿼리 실행으로 각각의 book이 담는 writer 조회