Spring/JPA

태태개발일지(JPA트러블 슈팅)

태태코 2023. 8. 16. 11:05
반응형

-N+1 문제란?

연관 관계에서 발생하는 이슈로 연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어오게 된다. 이를 N+1 문제라고 한다. 
 

-그렇다면 Lazy를 사용하면 해결되는가?

결과는 아니다

EAGER 객체를 부르면 연관된 데이터를 그냥 다 불러온다.

lazy ->  get을 했을경우 가능하다. -> @Transtaion으로 되어있어 영속성이 가능할 때 까지

라는 특성을 가지지만 결국 lazy로 get을 통해 불러올경우 쿼리가 N만큼 늘어나 동일 하다는 것이다.

Json으로 파싱할때 엔티티를 getter로 참조하게되는데 그때 lazy로 되어있다고해도 쿼리가 발생하기떄문에 @ToSTring.Exclude를 사용해줘야 재 역할을 한다.

 -N+1은 왜 발생하는 것일까?

jpaRepository에 정의한 인터페이스 메서드를 실행하면 JPA는 메서드 이름을 분석해서 JPQL을 생성하여 실행하게 된다. JPQL은 SQL을 추상화한 객체지향 쿼리 언어로서 특정 SQL에 종속되지 않고 엔티티 객체와 필드 이름을 가지고 쿼리를 한다. 그렇기 때문에 JPQL은 findAll()이란 메소드를 수행하였을 때 해당 엔티티를 조회하는 select * from ? 쿼리만 실행하게 되는것이다. JPQL 입장에서는 연관관계 데이터를 무시하고 해당 엔티티 기준으로 쿼리를 조회하기 때문이다. 

 

-해결방안

join fetch를 사용한다!!!!! 그러면 query가 N개 나오는 문제를 해결할 수 있을 것이다.

@EntityGraph(attributePaths="comments")

EntityGraph사용. 

 

-단점

아무래도 fetch join을 사용하면 lazy로 설정해두어도 쿼리가 일어나면 join을 통해 모든 데이터를 불러오기 때문에 의미가 없어지고 pagenation이 불가능해진다. 그리고 중복값이 발생하게 된다.

 

<이거를 통해 해결하자>

@Fetch(FetchMode.SUBSELECT)
@BatchSize(size=5)

 

 

조회할때 일어날 수 있는 Query문제 

여러개의 업데이트시 @DynamicUpdate를 사용하면 쿼리가 간단해진다.

DrityCheck -> @Transcationall을 통해 영속성에 들어온 녀석을 save하지 않았을때 query가 발생하게 되는 현상 (readOnly = true)로 해결한다.

반응형

'Spring > JPA' 카테고리의 다른 글

태태개발일지 - JPA Auditing  (2) 2024.10.22
태태개발일지(EVENT)  (1) 2023.12.04
태태개발일지(query method)  (0) 2023.08.21
태태개발일지(연관관계 JPA)  (0) 2023.08.17
태태개발일지(JPA)  (0) 2023.08.10