CS

N+1문제의 발생이유와 해결방법

jungmin.park 2023. 12. 27. 14:03
N+1 문제의 발생 이유와 해결 방법에 대해 설명해주실 수 있을까요? 해결 방법은 3가지 이상 말씀해주시면 좋습니다.

 

N+1 문제란?

 

N+1 문제는 데이터베이스 쿼리를 실행할 때 발생할 수 있는 성능 문제 중 하나로, 쿼리 실행 시 추가적인 N개의 쿼리가 발생하여 성능저하를 초래할 수 있습니다. 

이는 주로 ORM(Object-Relation Mapping)를 사용하는 경우 발생하며, 한 번의 부모 쿼리로 N개의 자식 쿼리를 가져오는 방식에서 문제가 발생합니다.

Lazy Loading(지연 로딩) : 연관된 데이터가 실제로 필요할때만 로드되도록 설계된 방식이지만, 이를 잘못 사용할 경우 여러번의 쿼리가 발생하여 N+1 문제가 발생할 수 있습니다. 

Eager Loading(즉시 로딩) : Eager 전략으로 데이터를 조회하는 경우 N+1 문제가 발생할 수 있습니다.

 

 

Eager(즉시 로딩)인 경우

  • JPQL에서 만든 SQL을 통해 데이터를 조회
  • 이후 JPA에서 Fetch 전략을 가지고 해당 데이터의 연관 관계인 하위엔티티를 추가 조회시 N+1 문제 발생

Lazy(지연 로딩)인 경우

  • JPQL에서 만든 SQL을 통해 데이터를 조회
  • JPA에서 Fetch 전략을 가지지만, 지연 로딩이기 때문에 추가 조회는 하지 않음
  • 하지만, 하위 엔티티를 가지고 작업하게 되면 추가 조회가 발생하기 때문에 결국 N+1 문제가 발생하게 된다.

해결방법

  • Join Fetch 사용 : 조인을 통해 필요한 모든 데이터를 한 번에 가져오는 방식으로 문제를 해결할 수 있습니다. 
  • 캐싱 사용 : 자주 사용되는 데이터를 캐싱하여 데이터베이스 쿼리 횟수를 줄여 성능을 향상시킬 수 있습니다.
  • Batch Fetching 사용 : 데이터베이스에 배치 쿼리를 보내 여러 엔티티를 한 번에 가져오는 방식으로 성능을 향상 시킬 수 있습니다.

 

 


N+1문제란 1번의 쿼리를 날렸을 때 의도하지 않은 N번의 쿼리가 추가적으로 실행되는 것을 의미하며 Jpa Repository를 활용해 인터페이스 메소드를 호출할 때 1:N또는 N:1 관계를 가진 엔티티를 조회할 때 발생합니다. 즉시로딩인 경우 JPQL에서 만든 SQL을 통해 데이터 조회 시 Fetch 전략을 가지고 해당 데이터의 연관 관계인 하위 엔티티들을 추가로 조회할 때 발생하게 되고, 지연로딩인 경우 조회 시 Fetch 전략을 가지지만 추가 조회는 하지 않지만 하위 엔티티를 가지고 작업을 하게 되면 추가 조회가 발생하기 때문에 결국 N+1 문제가 발생하게 됩니다. N+1의 해결방법은 Join Fetch 사용하거나, 캐싱을 사용하거나, Batch Fetching 사용하여 문제를 해결 할 수 있습니다. Join Fetch는 Join을 통해 필요한 모든 데이터를 한 번에 가져오는 방식으로 문제를 해결 할 수있으며 자주 사용되는 데이터를 캐싱하여 데이터베이스 쿼리 횟수를 줄여 성능을 향상시킬 수 있습니다. 마지막으로 데이터베이스에 배치 쿼리를 보내 여러 엔티티를 한 번에 가져오는 방식을 성능을 향상 시킬 수 있습니다.

 

 

Reference


https://velog.io/@coco_116/N1-%EB%AC%B8%EC%A0%9C%EC%9D%98-%EB%B0%9C%EC%83%9D-%EC%9D%B4%EC%9C%A0%EC%99%80-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95%EC%97%90-%EB%8C%80%ED%95%B4-%EC%84%A4%EB%AA%85%ED%95%B4%EC%A3%BC%EC%8B%A4-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C%EC%9A%94-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95%EC%9D%80-3%EA%B0%80%EC%A7%80-%EC%9D%B4%EC%83%81-%EB%A7%90%EC%94%80%ED%95%B4%EC%A3%BC%EC%8B%9C%EB%A9%B4-%EC%A2%8B%EC%8A%B5%EB%8B%88%EB%8B%A4