JPA 란 무엇인가에 대해, JPA 를 사용할 때 맞닥뜨릴 수 있는 N+1 문제에 대한 정리가 필요하여 글을 포스팅 한다.
1. JPA (Java Persistence API)
- 개념
- Java ORM 기술에 대한 표준 명세로, Java 의 객체와 DB 를 매핑하는 인터페이스 역할 수행
2. N+1 문제
- 개념
- 요청이 1개의 쿼리로 처리 되기를 기대했는데, N개의 추가 쿼리가 발생하는 현상
- 발생 원인
- JPQL을 생성하여 실행할 때, 연관 관계 데이터를 무시하고 해당 Entity 기준으로 쿼리를 조회하기 때문
- 해결 방법
- 1) Fetch Join
- 연관된 Entity 또는 Collection 을 한 번에 같이 조회하는 기능
- 연관된 Entity 까지 같이 영속성 컨텍스트에 올림
- 그러나, Fetch Join 사용 시 한계
- 한계 1) OneToMany 관계에서 페이징 처리할 때 중복된 데이터가 발생하는 문제 발생
- 그 문제는 데이터 전체를 Full-Scan 해서 가져오고, 메모리에서 페이징 처리를 하여 메모리 부하 발생한다는 것이다.
- 해결 방법 1) ManyToOne 일 때 페이징 처리
- 해결 방법 2) @BatchSize 사용
- 연관된 Entity 를 조회할 때 지정된 Size 만큼 SQL 의 IN 절을 사용하여 조회
- 그러나 연관 관계 데이터의 최적화 데이터 Size 를 아는 것은 어렵다
- 한계 2) 연관 관계를 설정해 놓은 FetchType 을 사용할 수 없음
- 참고) 실무에서 글로벌 로딩 전략은 모두 지연 로딩으로 하고, 최적화가 필요한 부분에 Fetch Join 을 이용
- 2) @EntityGraph
- attributePaths 에 쿼리 수행 시 바로 가져올 필드 명을 설정
3. 출처
- https://www.youtube.com/watch?v=ni92wUkAmQI [ 우아한 테크 - 10분 테코톡, 수달의 JPA N+1 문제 ]
- https://incheol-jung.gitbook.io/docs/q-and-a/spring/n+1