코딩항해기

[DBMS] N+1 문제 본문

DBMS

[DBMS] N+1 문제

miniBcake 2024. 12. 20. 13:38

 

N+1 문제

N+1 문제는 ORM을 사용할 때 발생하는 대표적인 성능 문제다. 하나의 쿼리로 N개의 데이터를 가져온 후, 연관된 데이터를 가져오기 위해 N번의 추가 쿼리가 발생하는 현상을 말한다.

 

예시

게시글과 댓글의 관계를 예로 들면, 한 게시글에는 여러 개의 댓글이 달릴 수 있는 일대다 관계일 때,

더보기
@Entity
public class Post {
    @Id
    @GeneratedValue
    private Long id;
    
    private String title;
    
    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
    private List<Comment> comments;
}

@Entity
public class Comment {
    @Id
    @GeneratedValue
    private Long id;
    
    private String content;
    
    @ManyToOne(fetch = FetchType.LAZY)
    private Post post;
}
// 최초 게시글 목록을 가져오는 쿼리 1번 실행
List<Post> posts = postRepository.findAll();

// 각 게시글의 댓글을 조회할 때마다 추가 쿼리 발생
for (Post post : posts) {
    List<Comment> comments = post.getComments(); // N번의 추가 쿼리 실행
    System.out.println("댓글 수: " + comments.size());
}

 

N+1문제가 발생한다.

 

 

해결하기

이를 해결하기 위해서는 fetch join을 사용하거나, EntityGraph를 사용하는 방법이 있다.

Fetch join의 경우 연관된 엔티티를 join문으로 한 번에 조회하는 방법이고, EntityGraph의 경우는 JPA가 제공하는 어노테이션을 활용하는 방법이다. 또는 BatchSize를 지정해 연관된 데이터를 조회할 때 지정된 크기만큼 한 번에 조회하는 방법을 사용할 수 있다.

 

Fetch 방식

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
    @Query("SELECT p FROM Post p JOIN FETCH p.comments")
    List<Post> findAllWithComments();
}

// 사용 예시
List<Post> posts = postRepository.findAllWithComments(); // 한 번의 쿼리로 모든 데이터 조회

 

Fetch 방식 쿼리 비교

SELECT * FROM post; -- 1번 쿼리
SELECT * FROM comment WHERE post_id = 1; -- N번 실행
SELECT * FROM comment WHERE post_id = 2;
SELECT * FROM comment WHERE post_id = 3;
...

 ⇃
 
SELECT p.*, c.* 
FROM post p 
LEFT JOIN comment c ON p.id = c.post_id; --쿼리 하나로 해결

 

 

N+1 문제를 해결할 때는 상황에 맞는 적절한 전략을 선택해야 한다. 데이터의 양이 많은 경우 Fetch Join은 메모리 사용량이 증가할 수 있으며, 페이징 처리가 불가능할 수 있다. 이런 경우 BatchSize 설정이나 다른 최적화 방법을 고려해야 한다.

'DBMS' 카테고리의 다른 글

[DBMS] ACID  (0) 2024.12.19
[DBMS] Eager Loading & Lazy Loading  (0) 2024.12.18
[DBMS] ORM (Object-Relational Mapping)  (0) 2024.12.17
[DBMS] PostgreSQL 이해 (ORDBMS)  (0) 2024.11.23
[DBMS] MongoDB 이해 (NoSQL)  (0) 2024.11.22