적용에 대한 고민
우선 적용 이유는 데이터가 많아질수록 뒤에 있는 데이터에 접근하는 시간이 길어지는데 이를 줄이고자 했습니다.
* 데이터가 적어도 100만건 이상은 돼야 차이가 유의미 해지는데 이 정도로 뒤에 있는 데이터를 조회할 일이 있는가?
-> 조회하는 경우가 거의 없다가 현실적이지만 누군가는 정말 끝까지 탐색할 수도 있는것이고 누군가는 악의적으로 접근하여 DB connection을 점유해버릴 수도 있기 때문입니다.
on offset 성능 비교(데이터 2000만건)
offset을 활용해 페이징 처리를 했을 때는 끝에있는 데이터 999990 ~ 999999를 가져오는데 0.35초가 걸렸습니다.
이는, offset방식이 999990행까지의 레코드를 건너 뛰는 방식으로 동작하기 때문입니다. 건너 뛰어야 하는 레코드의 수가 많아질수록 성능은 저하됩니다.
no offset 성능 비교(클러스터링 인덱스 이용)
이제 데이터를 읽어오는 시작점을 offset을 이용하지 않고 클러스터링 인덱스를 이용해 접근합니다. id는 primary key이기 때문에 클러스터링 인덱스가 적용돼 있습니다. 모든 페이지에 대한 조회 성능이 동일해집니다.
이해가 어려웠던 부분
제가 처음에 헷갈렸던 부분은 id < lastId 조건을 만족하는 데이터 검색 과정의 동작 방식이었습니다.
만약 id < 1,00,000라면 100만개의 데이터를 다 찾아와서 limit에 따라 10개를 추출해내는 작업일텐데 999991 ~ 10000000으로 걸어줘야 하는게 아닌가?
이에 대한 답은 table full scan과 index range의 차이였습니다.
table full scan: 정렬되어있지 않기 때문에 조건에 해당하는 데이터를 테이블 전체에 순차적으로 접근해 찾아내야하는 방식
추가사항
한가지 더 궁금했던 점은 offset과 index를 이용한 탐색 모두 적용된다면 어떻게 동작할까 였습니다.
결과는 다음과 같았습니다.
검색 자체는 인덱스를 타고 빠르게 되지만 offset에 의해 999990개의 건너뛰기 때문에 성능이 저하된걸 볼 수 있습니다.
구현 코드
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(
ltItemId(lastItemId), // where id < lastId
eqToSearchText(searchText),
eqNotDeleted(),
eqBidding(isAll)
)
.orderBy(orderBySortCode(sortCode)) // order by id desc
.limit(pageable.getPageSize())
.fetch();
}
private BooleanExpression ltItemId(Long itemId) {
if (itemId == null) {
return null;
}
return item.id.lt(itemId);
}
- 마지막 id < lastId로 적용한 이유는 id순으로 desc정렬 되어있기 때문에 최신 데이터를 불러오기 위함입니다.
- 첫 번째 페이지에서는 기준이 되는 id를 알 수 없기 때문에 동적쿼리를 적용했습니다.
참고
1. 페이징 성능 개선하기 - No Offset 사용하기 (tistory.com)
1. 페이징 성능 개선하기 - No Offset 사용하기
일반적인 웹 서비스에서 페이징은 아주 흔하게 사용되는 기능입니다. 그래서 웹 백엔드 개발자분들은 기본적인 구현 방법을 다들 필수로 익히시는데요. 다만, 그렇게 기초적인 페이징 구현 방
jojoldu.tistory.com
'Project > Bidderown' 카테고리의 다른 글
실시간 알림을 위한 개인 소켓 구독 (0) | 2023.09.09 |
---|---|
페이징 처리 성능 개선(3) - Covering Index (0) | 2023.08.14 |
페이징 처리 성능 개선(2) - Covering Index (0) | 2023.08.13 |