한정된 네트워크 자원을 효율적으로 활용하기 위해 특정한 정렬 기준에 따라 데이터를 분할하여 가져오는 것
1) 오프셋 페이징
2) 커서 페이징
SELECT * FROM `user` ORDER BY id DESC LIMIT 20, 40
await this.userRepository
.createQueryBuilder("user")
.offset(0).limit(10).getRawMany()
offset : 1부터 시작하는 페이지
limit : 한번에 불러올 페이지
가장 쉽고 빠르게 페이징 할수 있는 방법이지만 해당 방법을 사용시 몇가지 문제점이 생긴다.
클라이언트가 가져간 마지막 row의 순서상 다음 row들을 n개 요청/응답하게 구현
이 전에 받은 데이터 이후 몇개를 주세요 라고 요청하는 방식
해당 방식은 Cursor을 하나 설정해줘야한다. 고유한 값으로 해당 커서는 CONSAT() 을 이요해서 만들기도 하고 id 값을 사용하기도 한다.
가장 간단하게는 id기준으로 10개씩 보내줬다. (정렬 후)
이렇게 하면 처음 호출시에는 10개의 id를 그 후부터는 이전에서 보내줬던 마지막 아이디를 넣어주면 그 뒤 10개를 보내주는 아주 간단한 커서기반 페이지네이션이 된다.
if(cursor){
queryBuilder.andWhere('user.id < :cursor' , { cursor })
}
queryBuilder.orderBy("user.id", "DESC").offset(0).limit(10).getRawMany()
두가지 parameter 기준 정렬도 가능하다.
SELECT id, name, age
FROM `user`
WHERE
(age > 20
OR
(age = 20 AND id > 14))
ORDER BY price ASC, id ASC
LIMIT 10
하지만 해당 방법으로 페이징을 할 경우 또 두가지 문제점이 있어 커스텀 CURSOR을 사용하는 경우가 많다.
1. 대부분의 RDBMS는 WHERE에 OR-clause 를 사용하면 인덱싱을 제대로 못 태움.
2. 클라이언트가 ORDER BY에 걸려있는 모든 필드를 알아야하고, 매 페이지 요청시마다 이 값들을 전부 보내야 함.