쿼리문 최적화

MoonJaeGyeong·2024년 11월 11일
1

오류 해결

목록 보기
4/4

문제 상황


이게 API 1회 조회 시 날아가는 쿼리문의 양이다.. Reservation 을 조회 시 마다 해당 테이블에 Counselor 가 같이 있는데 해당 테이블을 예약 갯수 만큼의 쿼리문이 추가적으로 날라가는 듯 하다.

이렇게 계속 많은 양의 쿼리문은 성능을 저하시키고 서버를 개발한다면 꼭 최적화 해야하는 부분이라고 생각한다.

그렇다면 해결 방법이 뭐가 있을까?


해결 방법


1. @EntityGraph

일단 나는 QueryDsl 을 쓰지 않겠다 하면 해당 방법이 존재하겠다. @EnittyGraph 가 뭔지 나는 몰랐었는데, 해당 어노테이션은 N+1 문제 해결 및 성능 최적화에 간편하게 도움을 줄 수 있게 Fetch Join 을 적용시켜주는 어노테이션이다. 필요한 부분에 아래와 같이 적용하면 된다.

    @EntityGraph(attributePaths = {"counselor"})
    @Query("SELECT r FROM Reservation r LEFT JOIN r.counselor c WHERE r.account.email = :accountEmail ORDER BY r.createdAt DESC")
    List<Reservation> findAllByAccount_EmailOrderByCreatedAtDesc(String accountEmail);



주의 사항

@EntityGraph 는 left outer join 만 지원한다.

다른 방식의 경우 JPQL 을 직접 작성해 fetch join 을 사용해야만 한다.


2. QueryDsl

아니면 QueryDsl 을 사용하여 FetchJoin 을 진행하면 되는데, Query Dsl 의 경우 다음과 같이 작성하면 된다.

QueryDslConfig.java

@Configuration
public class QueryDslConfig {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }

}

build.gradle

	// Querydsl-JPA
	implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
	annotationProcessor("com.querydsl:querydsl-apt:5.0.0:jakarta")
	annotationProcessor("jakarta.persistence:jakarta.persistence-api")
	annotationProcessor("jakarta.annotation:jakarta.annotation-api")

CustomRepositoryImpl.java

@RequiredArgsConstructor
public class CustomReservationRepositoryImpl implements CustomReservationRepository{

    private final JPAQueryFactory queryFactory;

    @Override
    public List<Reservation> findAllByAccountEmail(String email){
         return queryFactory.select(reservation)
                 .from(reservation)
                 .leftJoin(reservation.account, accountDetail)
                 .leftJoin(reservation.counselor, counselor)
                 .where(accountDetail.email.eq(email))
                 .orderBy(reservation.createdAt.desc())
                 .fetchJoin().fetch();
    }
}

이렇게 작성하면 QueryDsl 을 이용하여 fetch join을 사용할 수 있다.


문제 해결

이와 같이 매 조회 시 마다 쿼리문이 날라가던 문제가 해결된 것을 볼 수 있다.

최적화 전 API 성능

최적화 후 API 성능

약 39.3%의 성능 개선을 확인할 수 있습니다.

profile
내 맘대로 끄적이는 개발 블로그

0개의 댓글

관련 채용 정보