[One Day One Question]
JPA의 N+1에 대해서 설명해주세요
JPA의 N+1 문제는 데이터베이스에서 쿼리를 수행할 때 발생하는 성능 저하 문제입니다. 이 문제는 주로 연관된 엔티티를 조회할 때 발생하며, 기본적으로 N개의 엔티티를 조회할 때 추가로 N개의 쿼리가 발생하는 상황을 의미합니다. 예를 들어, 게시글과 댓글을 조회할 때, 게시글을 조회한 후 각 게시글마다 댓글을 조회하기 위해 추가 쿼리가 발생한다면 N + 1 문제가 발생한 것입니다.
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@OneToMany(mappedBy = "post")
private List<Comment> comments;
// getters and setters
}
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;
@ManyToOne
@JoinColumn(name = "post_id")
private Post post;
// getters and setters
}
public List<Post> getAllPosts() {
List<Post> posts = postRepository.findAll(); // 1개의 쿼리
for (Post post : posts) {
System.out.println(post.getComments().size()); // 각 포스트에 대해 댓글 수를 조회
}
return posts;
}
위의 getAllPosts 메서드는 findAll()을 호출하여 모든 Post를 가져옵니다. 이때, Post에 대한 쿼리는 1번 실행되지만, 각 Post에 대한 Comment를 조회할 때마다 추가 쿼리가 실행됩니다. 만약 10개의 Post가 있다면, 총 11개의 쿼리가 실행됩니다 (1 + 10)
해결 방법
1. Fetch Join 사용
Fetch Join은 연관된 엔티티를 한 번의 쿼리로 조회할 수 있습니다.
- Repository에 JPQL로 Fetch Join 쿼리 작성
@Query("SELECT p FROM Post p JOIN FETCH p.comments") List<Post> findAllWithComments();
2. @EntityGraph 사용
@EntityGraph는 JPA 표준 어노테이션으로 Fetch Join을 선언적으로 설정할 수 있습니다.
- Repository에 @EntityGraph 작성:
@EntityGraph(attributePaths = "comments")
@Query("SELECT p FROM Post p")
List<Post> findAllWithComments();
3. Batch Size 설정
Batch Size는 연관 엔티티를 지연 로딩 시, 한 번에 여러 엔티티를 조회할 수 있도록 설정합니다. 이를 통해 N번의 추가 쿼리를 줄이고, Batch 단위로 쿼리를 실행합니다.
- Batch Size 설정 방법:
- 엔티티에 @BatchSize 어노테이션 추가:
@OneToMany(mappedBy = "post")
@BatchSize(size = 10)
private List<Comment> comments;
'cs > ODOQ' 카테고리의 다른 글
[ODOQ] 일급 컬렉션 (0) | 2024.11.27 |
---|---|
[ODOQ] Checked Exception, Unchecked Exception (0) | 2024.11.26 |
[ODOQ] TCP와 UDP의 차이점 (1) | 2024.11.25 |
[ODOQ] HTTP와 HTTPS의 차이점 (0) | 2024.11.24 |
[ODOQ] 엔티티 매니저란? (0) | 2024.11.22 |