CS

[JPA] N+1

KJihun 2023. 10. 30. 15:49
728x90

 

N+1 문제

데이터베이스에서 데이터를 조회할 때 발생하는 성능 문제 중 하나다.

조회된 데이터 갯수(n) 만큼 연관관계의 조회 쿼리가 추가로 발생하는 현상이다.

이로 인해 불필요한 쿼리가 발생하여 성능이 저하된다.



발생 이유

연관된 여러개의 테이블이 존재할 때, 한쪽 테이블만 조회하고 연결된 다른 테이블은 따로 조회하기 때문에 발생한다.

Eager는 조회 즉시 N+1 문제가 발생하고, Lazy는 연관된 데이터를 조회하려고 할 때 발생한다.

 


해결 방법

1. Fetch Join

JPQL을 사용하여 DB에서 데이터를 가져올 때 처음부터 연관된 데이터까지 같이 가져오게 하는 방식이다.

장점
  - 데이터베이스에서 한 번의 쿼리로 필요한 데이터를 모두 가져올 수 있다.
  - 지연 로딩을 사용하지 않기 때문에 성능이 향상된다.

 

단점
  - 불필요한 데이터까지 가져올 수 있어서 데이터 전송량이 늘어날 수 있다.
  - 연관된 엔티티가 많으면 조인의 복잡성이 증가할 수 있다.

  - FetchType을 사용할 수 없으므로, FetchType을 Lazy로 설정해놓는 것이 무의미해진다.

  - 페이징 쿼리를 사용할 수 없어서 페이징 단위로 데이터를 가져오는 것이 불가능하다.

 


2. EntityGraph 

데이터를 로딩할 때 특정한 엔티티 그래프를 적용하여 필요한 데이터만 가져올 수 있도록 도와주는 기능이다.

 

장점
  - 필요한 데이터만 가져올 수 있어서 불필요한 데이터 전송량을 줄일 수 있다.
  - 코드에서 로딩 전략을 명시적으로 표현할 수 있다.

단점
  - 추가 작업이 필요하다.

  - left outer join이기 때문에 필요 이상의 컬럼이 조회될 수 있다.

 



3. Batch Size 설정

지연 로딩(Lazy Loading)을 사용하는 경우, 데이터를 일괄 처리하는 갯수를 설정하여 성능을 최적화하는 방법
@OneToMany` 어노테이션에 `@BatchSize`를 설정하여 일괄 처리를 활용한다.

@ManyToOne을 사용할 경우,  해당 필드가 lazy(lazy=true)로 표시된 경우에만 의미가 있다.

장점
  - 한 번의 추가 쿼리로 여러 데이터를 가져올 수 있어 N+1 문제를 완화시킬 수 있다.
  - 지연 로딩을 사용할 때 효과적이다.

단점
  - 크기가 너무 크면 메모리 부하가 발생할 수 있다.

 

 

 

4. @Fetch(FetchMode.SUBSELECT)

@Fetch(FetchMode.SUBSELECT)은 Hibernate의 기능으로, 연관된 엔터티들을 한 번에 가져오는 방식이다.

 

 

'CS' 카테고리의 다른 글

[mySQL] 면접 예상 질문  (0) 2023.11.07
[Network] websocket & stomp, 실시간 통신  (0) 2023.11.07
[JPA] ORM, JPA  (1) 2023.10.30
[JPA] Propagation  (0) 2023.10.27
[DB] 트랜잭션(Transaction, ACID)  (0) 2023.10.27