일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 전략 패턴이란
- mongodb lookup
- javav 1676
- kotiln const
- spring mongodb
- 백준 1504 java
- kotiln functional interface
- spring mongodb switch
- java 1238
- spring mongoTemplate
- nodejs rabbitmq
- kotiln const val
- java 파티
- java 1509
- 익명 객체 @transactional
- 자바 1676
- 자바 백준 팩토리얼 개수
- 안정해시
- java 팩토리얼 개수
- ipfs bean
- 백준 특정한 최단 경로
- ipfs singletone
- 백준 2252 줄세우기
- 백준 연결요소 자바
- java 백준 1509
- spring mongoTemplate switch
- go
- rabbitmq 싱글톤
- Java Call By Refernce
- Spring ipfs
- Today
- Total
공부 흔적남기기
JPA N+1문제 트러블슈팅 본문
이번에 새로운 프로젝트를 하면서 JPA를 사용하여 쿼리를 사용하였다.
맨처음 개발할때 아무생각없이 spring data jpa 인터페이스를 통해 마구잡이로 개발하여
n+1 문제가 안나오는 곳을 찾을수가 없었다.
그래서 N+1문제가 문제가 뭔데
N+1문제는 select문을 1개를 날리겠다는 의도로 쿼리를 했지만 추가로 N번의 쿼리가 생기는 문제이다.
이 문제는 entity간의 연관관계 때문에 일어나게 된다.
N+1문제를 트러블 슈팅하기전에 먼저 FetchLazy와 FetchEager에 대해 알아보자
Lazy와 Eager의 설정은 하나의 엔티티를 select할떄 엔티티와 연관관계가 맺혀진 엔티티를 어떻게 처리할 것인지 정하는 설정이다.
Eager로 설정하게 되면 연관관계가 맺혀진 모든 엔티티를 한번에 다 가져오게된다.
Lazy로 설정하게되면 proxy객체로 대신하여 만들어 놓고 사용될때 1차캐시에 넣어 참조하여 사용하도록한다.
즉 따라서 Lazy를 사용하는 것이 권장된다. 왜냐하면 Eager로 걸어두면 사용하지 않을때도 마구잡이로 데이터들이 들어오기 떄문이다.
@OnetoMany는 기본이 fetchLazy이고 @XtoOne은 Eager이 기본이기 때문에 @XtoOne만 바꿔주면된다.
N+1 문제 트러블 슈팅
N+1문제는 N+1문제와 JPA가 돌아가는 구조를 이해했다면 엄청 쉽게 해결할 수 있다.
해결하는 방식은 두 가지인데 fetch join을 사용하는 방법과 batch_fetch_size를 거는 방법이 있다.
필자는 fetch join을 주로 사용하여 fetch join으로 해결하지 못하는 부분은 batch_fetch_size를 통해 해결하였다.
fetch join이 뭔데
fetch join은 jpa성능 최적화를 위한 join으로 일반 조인이 하나의 엔티티를 영속화 한다면 fetch join을 하게된다면 join이 걸린 entity를 함께 영속화시킨다.
참고로 Eager로 걸어놓고 jpql에서 일반 join을 써서 N+1문제를 해결해보겠다는 생각을 할 수도 있지만 일반 join은 select의 주체가되는 entity만 참조하기 떄문에 N+1문제는 해결되지 않는다.
그럼 batch_fetch_size는 또뭔데
batch_fetch_size는 아직 제대로 이해하지 못했지만 필자가 이해한바는 join된 엔티티를 조회할때 엔티티들의 pk를 하이버네이트에 차곡차곡 쌓아두고 batch_fetch_size만큼 차면 in절을 통해 select를 한번에 가져오는 것이다.(batch_fetch_size는 크게 설정해두어도 jpa내부에서 다시한번 최적화되서 사용되는 것 같다)
'web study > Spring' 카테고리의 다른 글
객체와 캡슐화에 대해서(객체지향적 코드를 짜는 이유) (0) | 2022.04.10 |
---|---|
단일책임원칙 위배 트러블 슈팅 ApplicationEventPublisher와 EventListner (0) | 2022.04.05 |
SpringBoot Redis를 활용한 Socket 통신(WebSocket, Stomp) (0) | 2022.03.09 |
Spring MVC Kakao소셜 로그인 방법과 과정 (0) | 2022.02.16 |
SpringSecurity 로그인 실패시 Http 400보내는 방법 (0) | 2022.02.13 |