Project/Bidderown

페이징 처리 성능 개선(3) - Covering Index

Seung__Yong 2023. 8. 14. 00:36

결과 비교

이번 테스트에서는 데이터 건수를 500만건으로 줄여 테스트 했습니다.

index적용(X) index적용(O) Covering Index적용
3.8sec 1.8sec 0.36sec

 

기존 코드(인덱스 적용 전,후)

service

@Transactional(readOnly = true)
public List<ItemsResponse> getItems(ItemsRequest itemsRequest, Pageable pageable) {
    List<ItemsResponse> items = itemCustomRepository.findItems(
            itemsRequest.getId(),
            itemsRequest.getS(),
            itemsRequest.getQ(),
            itemsRequest.isFilter(),
            pageable
    );
    return items;
}

repository

public List<ItemsResponse> findItems(Long lastItemId, int sortCode, String searchText, boolean isAll, Pageable pageable) {
    return queryFactory
            .select(
                    Projections.constructor(
                            ItemsResponse.class,
                            item.id,
                            item.title,
                            item.minimumPrice,
                            item.thumbnailImageFileName,
                            item.itemStatus,
                            item.expireAt
                    )
            )
            .from(item)
            .where(
                    eqNotDeleted(),
                    eqBidding(isAll)
            )
            .orderBy(orderBySortCode(sortCode))
            .limit(pageable.getPageSize())
            .offset(pageable.getOffset())
            .fetch();
}
  • postman으로 1000000번째 데이터를 요청한 결과 3.8초가 걸렸습니다.
  • 인덱스는 실제 DB에서 다음과 같은 쿼리를 날려 생성해주었습니다.
    create index deleted_status_expireAt on item(deleted, item_status, expire_at);
  • JPA를 이용하여 테이블 생성 시 index를 생성하고 싶다면 다음과 같은 형태로 작성하면 됩니다. 
    @Table(name = "item", indexes = @Index(name = "deleted_status_expireAt", columnList = "deleted, item_status, expire_at"))
  • 인덱스를 생성한 후에는 동일한 요청이 1.8초가 걸렸습니다.

개선 코드(Covering Index적용)

service

@Transactional(readOnly = true)
public List<ItemsResponse> getItems(ItemsRequest itemsRequest, Pageable pageable) {
    List<Long> ids = itemCustomRepository.findItemIdsByExpireAt(
            itemsRequest.getId(),
            itemsRequest.getS(),
            itemsRequest.getQ(),
            itemsRequest.isFilter(),
            pageable
    );

    List<ItemsResponse> items = itemCustomRepository.findItems(ids);
    return items;
}

repository

public List<Long> findItemIdsByExpireAt(Long lastItemId, int sortCode, String searchText, boolean isAll, Pageable pageable) {
    return queryFactory
            .select(
                   item.id
            )
            .from(item)
            .where(
                    eqToSearchText(searchText),
                    eqNotDeleted(),
                    eqBidding(isAll)
            )
            .orderBy(orderBySortCode(sortCode))
            .limit(pageable.getPageSize())
            .offset(pageable.getOffset())
            .fetch();
}

public List<ItemsResponse> findItems(List<Long> ids) {
    return queryFactory
            .select(
                    Projections.constructor(
                            ItemsResponse.class,
                            item.id,
                            item.title,
                            item.minimumPrice,
                            item.thumbnailImageFileName,
                            item.itemStatus,
                            item.expireAt
                    )
            )
            .from(item)
            .where(item.id.in(ids))
            .fetch();
}
  • 동일하게 postman으로 1000000번째 데이터를 요청했을 때 0.36초가 걸렸습니다.