1. N+1 문제란?
N+1 문제는 한 번의 쿼리로 N개의 연관된 엔티티를 가져올 때, 각각의 연관된 엔티티를 가져오기 위해 N번의 추가 쿼리가 실행되는 현상
2. 해결방법
- Global Fetch
- @ManyToOne 속성에 fetch 속성으로 LAZY로 설정
- 엔티티를 생성할 때(컴파일 시점) 결정 되는 연관관계 전략임
- Fetch Join
- JPQL의 fetch join을 사용하면 연관된 엔티티를 한 번의 쿼리로 함께 가져올 수 있음
- 조인할 때 연관된 엔티티나 컬렉션를 함께 조회하려고 할 때 사용하고, 결과는 EAGER 와 똑같지만 과정은 다름
List<Post> posts = entityManager.createQuery(
"SELECT p FROM Post p JOIN FETCH p.comments", Post.class)
.getResultList();
- Entity Graph
- @EntityGraph 어노테이션을 사용하면, 특정 엔티티를 조회할 때 어떤 연관 엔티티들을 Eager 로딩할지 세밀하게 지정가능
- 지연 로딩으로 설정되어 있으면 연관관계에서 종속된 엔티티는 쿼리 실행 시 select 되지 않고 proxy 객체를 만들어 엔티티가 적용 -> proxy 객체를 호출할 때마다 그때 그때 select 쿼리가 실행 되므로
- fetch 조인을 어노테이션으로 사용할 수 있도록 만들어 준 기능임
public interface CommentRepository extends JpaRepository<Comment, Long> {
@EntityGraph(attributePaths = {"thread"}, type = EntityGraph.EntityGraphType.LOAD)
List<Comment> findAll();
}
EntityGraphType.LOAD | EntityGraphType.FETCH |
attributePaths에 정의한 엔티티들은 EAGER, 나머지는 글로벌 패치 전략에 따 라 패치 | attributePaths에 정의한 엔티티들은 EAGER, 나머지는 글로벌 패치 전략에 따 라 패치 |
+ 성능 최적화 추가사항 )
- Batch Fetching
- 연관된 엔티티를 일정 크기의 배치로 묶어서 조회
@OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
@BatchSize(size = 10) // 여기에 배치 사이즈를 지정
private List<Comment> comments;
spring:
properties:
hibernate:
default_batch_fetch_size: 100
'TIL' 카테고리의 다른 글
[TIL] 20240311 JPA Query dsl - JPAQueryFactory (0) | 2024.03.11 |
---|---|
[TIL] 20240308 JPA Query dsl - QuerydslPredicateExecutor (2) | 2024.03.08 |
[TIL] 20240305 JPA 페이징 기능 (0) | 2024.03.05 |
[TIL] 20240304 JPA 1차캐시 / 2차캐시 (0) | 2024.03.04 |
[TIL] 20240226 Spring JPA Query method (1) | 2024.02.26 |