정산 서비스 성능 개선

ItemReader 성능 개선

초기 설계와 문제점: JpaPagingItemReader 의 성능 한계

처음에는 영속성 컨텍스트를 활용하기 위해 JpaPagePagingItemReader를 사용하여 데이터 읽기 작업을 구현하도록 설계하였다.

그러나, JpaPagingItemReaderoffset 기반 페이징 방식을 사용하기 때문에 대량 데이터 처리 시 성능 저하 문제가 발생하였다.

    select
        pje1_0.PAYMENT_ID,
        pje1_0.BALANCE_AMOUNT,
        pje1_0.CANCEL_DEADLINE,
        pje1_0.CONFIRM_DEADLINE,
        pje1_0.CREATED_AT,
        pje1_0.DELETED_AT,
        pje1_0.IDEMPOTENCY_KEY,
        pje1_0.IS_DELETED,
        pje1_0.ORDER_NAME,
        pje1_0.ORDER_PUBLIC_ID,
        pje1_0.PAYMENT_KEY,
        pje1_0.PAYMENT_PUBLIC_ID,
        pje1_0.PAYMENT_STATUS,
        pje1_0.TOTAL_AMOUNT,
        pje1_0.UPDATED_AT,
        pje1_0.USER_PUBLIC_ID 
    from
        ED_PAYMENT pje1_0 
    where
        pje1_0.PAYMENT_STATUS in (?, ?) 
        and pje1_0.CANCEL_DEADLINE<? 
    **limit
        ?, ? // offset, limit => Offset 기반으로 쿼리가 요청된다.**

대안 탐색

성능 저하 문제를 해결하기 위해 JdbcPagingItemReaderJdbcCursorItemReader 을 다음과 같이 검토하였다.

  1. JdbcPagingItemReader
  2. 커서 기반으로 데이터를 순차적으로 읽어와 연결 유지 시간이 길어짐

예시 코드

image.png

image.png

⇒ 데이터베이스 연결 시간과 메모리 효율성을 고려하여 최종적으로 JdbcPagingItemReader를 선택

하지만 둘 다 문자열 기반으로 쿼리를 작성하므로 최악의 경우 우리는 런타임에 에러를 맞이해야 한다.

최종: QueryDsl + CustomItemReader 구현

문자열 기반으로 쿼리를 작성하던 중 Type-Safe 한 쿼리를 작성할 수 있는 방법을 모색하였고, 최종적으로는 QueryDsl +커스터마이징 ItemReader 를 혼합하여 다음과 같은 이점을 갖게 되었다.

  1. 문자열 기반으로 쿼리를 직접 작성하지 않고 Type-Safe 하게 IDE 지원을 받으며 복잡한 쿼리까지 작성 가능