본문 바로가기

트러블 슈팅

N+1 문제 해결

728x90
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Request extends Timestamped {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "REQUEST_ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "POST_ID")
    private Post post;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "USER_ID")
    private User user;

    @Enumerated(value = EnumType.STRING)
    @Column(nullable = false)
    private RequestStatus requestStatus;

    public Request(Post post,User user){
        this.post = post;
        this.user = user;
        this.requestStatus = RequestStatus.PENDING;
    }

    public Request(Post post,User user,RequestStatus requestStatus){
        this.post = post;
        this.user = user;
        this.requestStatus = requestStatus;
    }

    public void updateStatus(UpdateRequestDto updateRequestDto) {
        this.requestStatus = updateRequestDto.getStatus();
    }
}

N+! 문제 발생                                                                                                      N+1 문제 해결

@Query("SELECT r from Request r join fetch r.post join fetch r.user where r.id=:id")
Optional<Request> findById_fetchUserAndPost(Long id);

request entity의 Post와 User의 FetchType이 lazy로 설정되어있어  하위 entity인 Post와 User를 참조할 경우 왼쪽의 그림처럼  N+1 쿼리 문제가 발생한다. fetch join을 이용하여 findbyId함수를  위의 JPQL로 바꾸면 오른쪽의 그림처럼 N+1 문제가 해결된다.

 

explain select * from springdb.request where springdb.request.request_id = 291;

explain select * from springdb.post where springdb.post.post_id = 198;

explain select * from springdb.user where springdb.user.user_id = 99;

explain select * from springdb.request as R join springdb.post as P  on P.post_id = R.post_id join springdb.user U on U.user_id = R.user_id  where R.request_id = 291;

검색되는 rows 값은 3으로 동일하지만 N+1 쿼리 문제가 발생하는 쿼리들의 duration을 합쳐보면 0.00095175 , N+1 쿼리 문제를 해결한 쿼리는 duration은 0.00044975이다. 쿼리 속도가 2배 이상 개선된 것을 볼 수 있다.

728x90

'트러블 슈팅' 카테고리의 다른 글

HashSet의 객체 중복 제거  (0) 2022.10.22