본문 바로가기
IT/DB

N+1 문제와 해결방법문제와 해결방법

by Cyber_ 2024. 11. 7.

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