N+1 문제란?
쿼리 한번으로 N 건의 데이터를 가져왔을 때, 데이터를 얻기 위해 N건의 데이터를 가져온 데이터 수만큼 반복해서 2차적으로 쿼리를 수행하는 문제
왜 발생하는가?
한 번의 쿼리로 N개의 관련 객체를 불러온 후, 각 객체에 대해 추가적인 쿼리가 필요할 때 사용.
예를 들어, 게시글 목록을 불러온 후 각 게시글의 작성자 정보를 불러오기 위해 별도의 쿼리를 실행하는 상황에서 만약, 100 개의 게시글이 있고 각 게시글마다 작성자 정보를 조회하는 쿼리를 실행한다면, 최초의 1번 쿼리와 각 게시글에 대한 100번의 쿼리, 총 101번의 데이터베이스 쿼리가 필요하게 되어 성능이 크게 저하 됨.
N+1 문제의 해결방법
조인(Joins)
SQL 조인을 사용하여 필요한 모든 데이터를 한번의 쿼리로 가져올 수 있습니다. 이 방법은 추가 쿼리 없이 관련 데이터를 함께 로드
사용 사례: 블로그 포스트와 작성자 정보를 동시에 조회하는 경우
SELECT posts,*, users.name, users.profile_image
FROM posts
JOIN users ON posts.user_id = users_id;
선택적 로딩(Selective Loding)
ORM을 사용하는 경우, eager loading 기법을 통해 관련 데이터를 사전에 로드하는 설정을 할 수 있습니다. 예를 들어, Django에선 selected 또는 prefetch_related 메소드를 사용하여 관련 갠체를 미리 불러올 수 있음.
사례: Django에서 여러 게시글과 그에 따른 댓글을 불러올 때
from django.db.models import Prefetch
from myapp.models import Post, Comment
posts = Post.objects.prefetch_related('comments').all()
for post in posts:
print(posts.title)
for comment in posts.comments.all():
print(comment.text)
배치(Batching)
필요한 데이터를 작은 단위로 나누어 여러 번에 걸쳐 요청하는 방식으로, 각 배치마다 필요한 데이터만 로딩하여 처리합니다.
사례: 대규모 이메일 사용자에게 알림 보내기
users = User.objects.all()
batch_size = 1000
for i in range(0, len(users), batch_size):
barch = users[i:i+batch_size]
sent_notification(batch) # 각 배치의 사용자들에게 알림을 전송하는 함수
'IT > DB' 카테고리의 다른 글
Eager Loding, Lazy Loading (1) | 2024.11.07 |
---|---|
DB에 이미지를 저장할까? URL을 저장할까? (0) | 2024.04.16 |
Django와 PostgreSQL 어울리는 이유 (0) | 2024.04.16 |
MySQL vs PostgreSQL (0) | 2024.04.16 |