빠에야는 개발중

N+1 문제 본문

공부/JAVA

N+1 문제

빠에야좋아 2020. 10. 28. 21:07

N+1 문제

무엇인가?

N+1 문제는 JPA에서 하나의 부모 객체와 다수의 자식 객체 데이터를 얻기 위해 메소드를 호출했을때 부모를 조회하는 쿼리 1개와 하위의 N개의 자식들을 조회하는 쿼리 N개가 발생하는 문제이다. 이는 1:N 관계에서 fetch type이 eager loading일 때 findAll() 따위로 전체를 조회하는 메소드를 사용하거나, lazy loading일 때 자식 객체를 반복문 따위로 순환 조회하는 과정에서 발생한다. 한번의 쿼리로 join해서 가져올 것을 자식 객체 수만큼의 쿼리를 사용하니 당연히 성능적으로 좋지 않다.

어떻게 해결하는가?

JPQL에서는 fetch join이라는 기능을 제공한다. 데이터를 한번에 가져올 수 있도록 해준다.
하지만 두 개 이상의 컬렉션을 가진 엔티티를 조회하게 되면 어떨까? fetch join을 복수의 컬렉션에 적용하면 카테시안 곱에 의해 중복 데이터가 발생하면서 MultipleBagFetchException이 발생한다. 이를 어떻게 해결할 것인가?

  1. list 대신 set을 사용해서 중복을 제거한다. set은 list와 달리 중복을 허용하지 않기 때문이다. 순서 보장을 위해서 LinkedHashSet을 사용한다.
    • 쿼리의 문제 때문에 자료형을 바꾸는 것은 좋지 않은 방법인 것 같다.
  2. default_batch_fetch_size 값을 조정해서 한 번에 여러개의 조건을 걸 수 있도록 할 수 있다. 실제 SQL에서는 WHERE ~ IN 절을 사용한다.
    • Fetch join과 함께 사용하여 가장 많은 데이터를 가져올 것으로 예상되는 컬렉션에 Fetch join을 걸고, 나머지 컬렉션에는 where in 절을 사용하면 최소한의 성능을 보장해줄 수 있을 것 같다.

'공부 > JAVA' 카테고리의 다른 글

OSIV  (401) 2020.10.28
CAS(Compare And Swap) 알고리즘  (0) 2020.08.06
String, StringBuffer, StringBuilder  (0) 2018.03.17
abstract class와 interface  (0) 2018.03.17
스트림 api  (0) 2018.03.01
Comments