본문 바로가기
영상 후기/Spring Boot

영상 후기 - [10분 테코톡] 수달의 JPA N+1 문제

by 올리브영 2023. 3. 31.
728x90
반응형

movie

JPA에서 N+1 문제란?

  • 요청이 1개의 쿼리로 처리 되길 기대했는데 N개의 추가 쿼리가 발생하는 현상

 

너무 많은 N+1 발생한다

  • JPA에서 다양한 연관관계를 지원해주고 있기 때문에(@OneToone, @ManyToOne 등등...)

 

지연(Lazy)로딩이란?

  • 지연로딩은 엔티티를 조회할 시 사용할때까지 데이터 로딩을 미루는 현상

 

JPQL(Java Persistence Query Language) 이란?

  • JPA는 엔티티르 중점으로 개발해주기 때문에 쿼리를 작성할 때도 엔티티를 대상으로 작성할 수 있게끔 JPQL이라는 기능을 지원

 

JPQL로 크루_Repository.findAll() 요청을 select * from crew 쿼리문으로 바꿔 데이터를 가져온다.

그리고 추가적으로 각 crew원의 할일 목록들을 가져온다면 crew수에 따라서 쿼리가 나간다.

이때 N+1문제가 발생한다. 즉, crew원 수에 따라서 쿼리가 더 발생된다.

 

 

해결방안 : Fetch join

  • 연관된 엔티티나 컬렉션을 한 번에 같이 조회하는 기능

 

쿼리문에 직접 fetch를 명시하는 방법과 어노테이션 이용하는 방법

 

// 방법 1
@Query("select c from 크루 c left join fetch c.목록")
List<크루> findAllJPQLFetch();

// 방법2(어노테이션 사용)
@EntityGraph

 

최초에 관련된 데이터를 한꺼번에 가져와서 객체화 해줬기 때문에 DB를 거치지 않고 데이터 꺼내서 반환

즉, 1개의 쿼리로 문제 해결

 

JPQL이 즉시(Eager)로딩 쿼리를 만들때에도 N+1 문제가 발생

 

JPQL이 쿼리로 변환 시켜주는 과정(즉시 로딩인 경우)

  • JPQL 자체가 엔티티를 기준으로 쿼리를 만들어준다.
  • 가지고 있는 엔티티의 연관관계는 무시하고, 첫 번째 쿼리를 만들 때에는 조회대상이 되는 엔티티 기준으로 쿼리를 만든다.
  • 처음에 A엔티티를 가져오고, 가져오고 나서야 연관관계를 확인해  연관관계가 있으면 글로벌 fetch 전략을 확인한다.
  • 전략이 즉시로딩인 경우 데이터를 바로 가져온다.
  • 이때 즉시 N번의 쿼리가 나가서 N+1문제가 생긴다.

 

해결방안은 즉시로딩은 최대한 사용하지말고, 지연 로딩 + fetch Join을 사용

728x90
반응형