DevBoi

[JPA] N+1 문제란 본문

Develop/[JPA]

[JPA] N+1 문제란

HiSmith 2022. 3. 18. 00:45
반응형

N+1 문제는, JPA의 Entity 조회시, Query 내부에 존재하는 다른 연관관계에 접근할 때 또 다시 한번 쿼리가 발생하는 

비효율적인 상황을 일컫는 말입니다.

 

1. 즉시 로딩 변경후, findAll로 조회하는 경우

OneToMany의 기본 로딩전략은 LAZY이지만, 해당 전략을 즉시로딩으로 변경하고

findAll을 하게되면, 하위 연관관계에 대한 전부를 조회해야하기 때문에 N+1이 발생할 수 있다.

 

ex. Post와 comment인 경우

Post를 조회하고, 하위의 comment를 전부 조회한다.

즉, Post의 개수대로, comment를 조회하는 쿼리가 추가로 나간다.

 

* 해결 방법 
지연로딩으로 변경

 

 

2.지연 로딩 변경 + Loop 조회

 

findAll로 가져올때는 N+1 발생하지 않는다(지연 로딩이기 때문에)

그런데, 해당 하위에, Post의 하위 연관관계가 맺어진 엔티티를 탐색할때는 문제가 된다.

왜냐면 지연로딩 이기때문에, 해당 엔티티를 접근할때 다시 DB에 조회쿼리가 나가는데

상위에서 find 해온 쿼리는 이미 끝난 상태라서, JOIN으로 쿼리 생성이 안된다.

따라서, Post의 ID로 조회할 수 밖에 없다.

루프에서 comment를 접근 할때마다, 쿼리가 나가게 된다.

 

* 해결 방법 

 

페치조인을 사용

페치조인을 사용하면 글로벌 로딩전략보다 우선순위를 가지게된다.

따라서 지연로딩 으로 글로벌 전략을 설정하고 페치조인을 필요할떄 사용하면,

조인쿼리 한번으로 필요한 엔티티를 전부 가져올 수 있다.

 

배치사이즈 지정 + 즉시로딩

JPQL 패치조인 대신 Batch크기를 저장하는 방법도 있다.

BatchSize를 지정하면 즉시로딩때 나가는 쿼리에 대한 제한을 둘 수 있다.

예를 들어서, batchSize를 지정한다고 가정하면

N+1문제를

이런식으로 최대 배치사이즈만큼의 in쿼리를 만들어준다.

제한을 수동적으로 숫자로 걸어주는 것이기때문에, 완벽하게 N+1 문제가 해결되지는 않는다는 건 참고하자

 

 

 

 

반응형

'Develop > [JPA]' 카테고리의 다른 글

[JPA] save, saveall의 성능차이  (0) 2022.03.20
[JPA] 패치조인이란  (0) 2022.03.20
[JPA] JPA 동작과정 (조회,저장, 수정)  (0) 2022.03.17
[JPA] 영속성 컨텍스트란?  (0) 2022.03.17
[JPA] 엔티티 생명 주기  (0) 2022.03.17