티켓 예매 사이트 - 5

JPA N+1 문제 해결

image.png

내 예매 내역을 조회하는 단순한 API에서 콘솔창에 SQL 쿼리가 20개 이상 쏟아지는 현상을 발견했다.
Fetch Join을 사용해 해결했으며, 혹시 몰라 배치 사이즈도 추가했다.

발생한 이후는 단일 테이블만 조회 -> Lazy로 설정되어 있기 때문에 비어있는 객체를 불러옴 ->
JPA가 DB에 필요한 데이터들을 SELECT로 계속 조회

적용한 코드

@Query("select distinct r from Reservation r " +
           "join fetch r.schedule s " +
           "join fetch s.performance p " +
           "left join fetch r.reservationSeats rs " +
           "left join fetch rs.seat " +
           "where r.member.id = :memberId " +
           "order by r.createdAt desc")


수정 전

Hibernate: 
    select
        p1_0.id,
        p1_0.category,
        p1_0.color,
        p1_0.date_text,
        p1_0.price,
        p1_0.slug,
        p1_0.subtitle,
        p1_0.symbol,
        p1_0.tag,
        p1_0.title,
        p1_0.venue 
    from
        performances p1_0 
    where
        p1_0.id=?
Hibernate: 
    select
        p1_0.id,
        p1_0.category,
        p1_0.color,
        p1_0.date_text,
        p1_0.price,
        p1_0.slug,
        p1_0.subtitle,
        p1_0.symbol,
        p1_0.tag,
        p1_0.title,
        p1_0.venue 
    from
        performances p1_0 
    where
        p1_0.id=? ........

수정 후

    select
        distinct r1_0.id,
        r1_0.created_at,
        r1_0.hold_token,
        r1_0.member_id,
        r1_0.order_id,
        r1_0.order_name,
        r1_0.paid_at,
        r1_0.payment_key,
        rs1_0.reservation_id,
        rs1_0.id,
        rs1_0.seat_id,
        s2_0.id,
        s2_0.hold_expires_at,
        s2_0.hold_token,
        s2_0.schedule_id,
        s2_0.seat_number,
        s2_0.status,
        s2_0.version,
        r1_0.schedule_id,
        s1_0.id,
        s1_0.performance_id,
        p1_0.id,
        p1_0.category,
        p1_0.color,
        p1_0.date_text,
        p1_0.price,
        p1_0.slug,
        p1_0.subtitle,
        p1_0.symbol,
        p1_0.tag,
        p1_0.title,
        p1_0.venue,
        s1_0.start_time,
        r1_0.status,
        r1_0.total_amount 
    from
        reservations r1_0 
    join
        performance_schedules s1_0 
            on s1_0.id=r1_0.schedule_id 
    join
        performances p1_0 
            on p1_0.id=s1_0.performance_id 
    left join
        reservation_seats rs1_0 
            on r1_0.id=rs1_0.reservation_id 
    left join
        seats s2_0 
            on s2_0.id=rs1_0.seat_id 
    where
        r1_0.member_id=? 
    order by
        r1_0.created_at desc


SQL 호출 개수가 줄었기 때문에 DB에 가는 부담이 줄어들었다.

이 프로젝트는 대규모 좌석 처리와 JPA의 SQL 호출의 워크플로우를 배우기 위해서 시작했으므로
일단은 여기서 마무리하려한다. 나중에 다른 대규모 처리를 활용해 보고 싶을 때 이 프로젝트에
붙여서 사용해보도록 하겠다.

댓글 0

댓글을 불러오는 중입니다.