본문 바로가기
스프링

JPA_N+1 문제

by 리포터12 2023. 8. 8.
728x90

EAGER VS LAZY

Eager(즉시 로딩) 방식

Eager(즉시 로딩) 방식을 사용하면 연관된 모든 값들을 가져온다.

따라서, 불필요한 정보, 중복 자료 등이 조회될 수 있으며, 어떤 쿼리가 추가적으로 발생하게 될지 예측하기 힘들다.

 

Lazy(지연 로딩) 방식

Lazy(지연 로딩) 방식을 사용하면 연관 엔티티가 사용될 때 해당 엔티티를 호출하게 되므로, 불필요한 조회를 막을 수 있다. 어떤 쿼리가 발생할지 비교적 예측이 쉬운 lazy 방식을 사용하자.

 

(EAGER 방식이 필요할 때가 있을지도 모른다. 그럼 그 때 또 알아 보자.)


N+1 이란?

1개의 쿼리로 조회한 엔티티와 연관관계를 맺고 있는 엔티티의 개수(N) 개 만큼 쿼리가 발생하는 문제이다. 

 

언제 발생하는가?

jpa를 통해 DB에 쿼리를 날려 받은 결과값을 사용하려고 할 때

조회 시도한 엔티티와 연관관계에 있는 엔티티의 값이 확인되지 않으면

해당 값들을 조회하기 위해 DB에 쿼리를 날린다.

 

어떤 문제가 있는가?

조회한 엔티티와 관계 있는 엔티티가 10,000 개일 경우,

[최초 조회를 위한 쿼리] x 1개

[데이터가 확인되지 않는 연관관계 엔티티를 위한 쿼리] x N개 

총 10,001 개의 쿼리가 발생한다.

쿼리가 많이 발생할수록 많은 비용이 발생하며, 성능 저하, DB 사망 등 다양한 문제로 이어질 수 있다. 

 

어떻게 극복 하는가?

fetch join, entity graph , dto 등으로 극복 가능하다.

 

Fetch join

- 1차 쿼리를 날릴 때 연관관계에 놓인 엔티티까지 한꺼번에 조회하여, 엔티티 미확인으로 인한 N개의 쿼리 발생을 막는다.

 

Entity Graph

- Fetch join 과 동일하게 연관관계에 놓인 엔티티까지 한번에 조회하여, 엔티티 미확인으로 인한 N개의 쿼리 발생을 막는다.

- 연관관계 엔티티 로딩 방식을 사전에 정의해서 사용한다.

- 단, Entity Graph 의 경우, Outer Join 이 발생하기 때문에 Inner Join 으로 동작하는 Fetch join 보다 성능면에서 떨어진다.

 

Dto

- 연관관계 엔티티 없이 필요한 테이블만 조회할 때 사용한다.

- JpaRepository 인터페이스에서 메서드 반환 타입을 필요한 필드로만 구성된 Dto로하여 Dto에 값을 주입하므로 +N 쿼리 발생을 막는다.

- 단, EntityToDto() 로의 변환작업이 반드시 필요하게 되므로 성능면에서 좋지 않을 수 있다.

 

 

참조

https://programmer93.tistory.com/83

 

JPA N+1 문제 해결 방법 및 실무 적용 팁 - 삽질중인 개발자

- JPA N+1 문제 및 해결 방법 - JPA를 사용하다 보면 의도하지 않았지만 여러 번의 select 문이 순식간에 여러 개가 나가는 현상을 본 적이 있을 것이다. 이러한 현상을 N+1문제라고 부른다. 해당 포스

programmer93.tistory.com

https://ttl-blog.tistory.com/1135

 

[JPA] N+1 문제가 발생하는 여러 상황과 해결방법

🧐 N + 1 문제 N + 1 문제는 연관관계가 설정된 엔티티 사이에서 한 엔티티를 조회하였을 때, 조회된 엔티티의 개수(N 개)만큼 연관된 엔티티를 조회하기 위해 추가적인 쿼리가 발생하는 문제를 의

ttl-blog.tistory.com

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발_엔티티 설계 시 주의점

https://www.inflearn.com/course/lecture?courseSlug=%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1&unitId=24284&tab=curriculum 

 

학습 페이지

 

www.inflearn.com

 

틀린 내용, 부족한 내용 태클 환영합니다.

728x90

댓글