99클럽 15일차 TIL: N+1문제

2024. 4. 18. 18:4999클럽/TIL

728x90
반응형

#1. 오늘의 학습 키워드

자바 스프링에서의 N+1 문제 에 대해서

  • JPA를 적용하는 과정에서, DB에 관련된 이모저모를 알아보는 과정에서 또 하나 재밌는 개념을 발견했다.
    • 트랜잭션, MVC 패턴 등은 이미 백엔드 코드 구현 중에 체득되어있는 지식들이지만, 해당 문제에 대한 대비는 아직 백엔드 코드에서 이뤄지지 않은 것 같다.
      • 혹은 눈치를 채지 못했거나.
    • 또한 분명 대학교 수업 시간에 배웠던 기억이 있지만, 가물가물하기에 다시 한 번 상기시켜보도록 하자.

#2. 공부한 내용

  • N+1 문제
    • 연관 관계에서 발생하는 이슈
    • 연관 관계가 설정된 Entity를 조회할 시, 조회된 데이터 개수 (N) 만큼 연관 관계가 있는 데이터를 추가로 조회하는 쿼리를 발생시키는 문제
      • 쉽게 말하면 1번 쿼리로 조회하고자 하는데 N 번의 추가적인 쿼리가 발생 되는 것이다.
      • 같은 결과를 리턴하더라도, 쿼리를 N 번 호출한다는 것은 심각한 성능 하락으로 이뤄질 수있다.
        • 데이터의 개수가 얼마나 늘어날지도 모르기 때문
    • 발생 이유
      • JPA는 메서드 이름을 분석하여 JPQL (Java Persistence Query Language, 즉 쿼리)를 생성하여 실행한다.
        • JPQL 은 오로지 Entity와 필드 이름만 가지고 쿼리를 생성되기에, 연관관계 데이터를 무시하고 해당 Entity기준으로 쿼리를 수행한다.
        • 따라서 연관 관계로 설정된 Entity 데이터가 필요하면 FetchType으로 지정한 시점에 쿼리를 별도로 호출하게 된다.
    • 해결방법
      1. Fetch Join
        • @Query 어노테이션으로 직접 쿼리(JPQL) 작성
          • @Query("select T from Table T join fetch T.id")
          • 이때 쿼리에서 원하는 대로 join 을 사용한다.
        • INNER JOIN
        • 단점은 연관관계에 설정해놓은 FetchType을 사용할 수 없고 그대로 JPQL 쿼리를 따른다는 것. 또한 페이징 단위로 조회하는 것이 불가
      2. EntityGraph
        • @EntityGraph 어노테이션에 attributePaths 옵션에 쿼리 수행시 가져올 필드명을 지정.
          • Lazy 가 아닌 Eager
        • OUTER JOIN
          • 중복된 데이터가 존재할 수 있어서 distinct 문을 Select 뒤에 쓰거나, 컬렉션에서 Set을 써서 중복 제거 가능.
      3. FetchMode.SUBSELECT
        • @Fetch(FetchMode.SUBSELECT)
        • 엔티티 자체를 조회하는 쿼리는 그대로 발생, 그리고 연관관계의 데이터에 대해서 조회하는 쿼리 따로 한 번 더 수행
          • 즉 쿼리 두 번으로 해결
      4. BatchSize
        • @BatchSize(size=3)
          • 연관된 엔티티를 조회할 때 지정된 size의 크기 만큼, SQL의 IN 절에 id (pk) 를 넣어서 조회의 횟수를 줄인다.
          • 즉 N / size의 크기 만큼의 쿼리가 발생한다.
        • 엔티티 자체와 연관 관계의 데이터를 동시에 조회

#3. 오늘의 회고

  • 결론을 짓자면 N+1 문제는 특히 대량의 데이터를 처리할 때 발생하는 성능 문제이다.
    • 연관 관계를 가진 엔티티를 조회할 때 발생하는 N개의 쿼리 때문에 초래된 성능 저하.
    • 여러가지 해결책이 제시되고 있으며, 최대한 적은 수의 쿼리로 원하는 데이터를 가져오는 것이 목표다.
  • 아직 JPA를 세팅하는 과정이라 제대로 해결책의 위력을 느끼지 못했지만, JPA에 대해 조금 더 이해할 수 있었다.
  • 그리고 역시 성능을 최적화하는 부분은 어떤 프레임워크든 제일 우선시 되는 부분이고, 사실 프레임워크 자체도 성능 향상과 편의성을 제공하기 위해 등장하였기에, 이렇게 많은 방법으로 N+1 문제 같이 성능의 치명적인 문제를 해결하려하는 것도 납득이 되는 부분이다.
728x90
반응형

'99클럽 > TIL' 카테고리의 다른 글

99클럽 17일차 TIL: Spring Webflux: Mono, Flux  (2) 2024.04.20
99클럽 16일차 TIL: Spring Webflux  (0) 2024.04.19
99클럽 14일차 TIL: Transaction  (0) 2024.04.17
99클럽 13일차 TIL: Hikari CP  (0) 2024.04.16
99클럽 12일차 TIL: MVC  (0) 2024.04.15