우리가 따라하고 있는 쿠팡에서는 페이징 기능이 있다!
그래서 상품 목록을 조회하는 API 에서 페이지 번호와 상품 개수를 함께 돌려줘야 하기 때문에
페이징 기능을 구현해보기로 했다 😀
어떻게 하면, 대용량 데이터에서도 빠르게 페이지 정보와 상품 정보를 가져올 수 있을까?
OFFSET
과 LIMIT
을 이용한다.SELECT *
FROM coupang.PRODUCT
WHERE is_rocket = 1
LIMIT 120
OFFSET 30000000;
Row lookup
를 사용한다.Inner Select
문에서 최대한 인덱스로 검색해서 id 를 가져온 다음에 JOIN
하여 Row lookup
을 최대한 늦추는 Late row lookup
을 활용하면, 성능을 향상 시킬 수 있다.SELECT *
FROM coupang.PRODUCT as p
JOIN (
SELECT id
FROM coupang.PRODUCT
LIMIT 120
OFFSET 30000000
) AS t
ON p.id = t.id;
offest
방식보다 약 70% 정도 성능이 향상되었다.Cursor
기반 페이징 방식은 조회 시작 부분을 인덱스로 빠르게 찾아 매번 첫 페이지만 읽도록 하는 방식이다.Offset
방식보다 훨씬 성능이 개선된다.직전 조회 결과의 마지막 ID
를 넘겨서 다음 페이지를 조회하는 방식인 것이다.SELECT *
FROM coupang.PRODUCT
WHERE id < 직전_조회_결과의_마지막_id
LIMIT 페이지 사이즈
cursor
방식은 성능 면에서 압도적이기 때문에 최대한 활용해보려고 노력했고, 이전 페이지 목록 마지막 커서
, 현재 페이지 목록의 조회 커서 목록
, 다음 페이지 목록 시작 커서
를 가져오는 방법 등을 생각했다. 하지만, 결국 모두 한계가 있어서 사용하기는 힘들었다.SELECT *
FROM coupang.PRODUCT
WHERE id >= 조회_시작점_id AND is_rocket = 1
LIMIT 120;
offest
방식보다 약 80배 이상 성능이 향상되었다.처음으로 돌아와서, "쿠팡에서는 어떻게 하고 있을까?" 추측해보기로 했다. 쿠팡 사이트를 탐색한 결과, 어떤 필터링 조건을 걸어도 항상 최대 17 페이지까지만 있는 것을 확인했다!
아마도 "모든 필터링 조건에 따라서 테이블을 분리해서 관리하는 대신, offset 방식으로 가져오는 게 아닐까?" 추측했다.
나중에 우리도 해당 방법으로 리팩토링을 시도해볼 생각이다!
대용량 더미 데이터를 생성하는 방법
- 프로시저 : 일련의 쿼리를 마치 하나의 함수처럼 실행하기 위한 쿼리의 집합 - 참고