티스토리 뷰

MongoDB의 데이터를 페이징 하기 위해 skip, limit을 사용하고 있었는데, 어느새부터 데이터를 가져오는데 수 초이상의 지연이 발생하였습니다.

문제점: skip, limit

collection.find().skip(pageSize*(pageNum-1)).limit(pageSize);

위 방법은 MongoDB에서 지원하는 일반적인 페이징 방식이지만, 컬렉션 내에 도큐멘트 수가 방대하다면 효율적이지 못한 방법입니다.

MongoDB에서 skiplimit을 이용한 페이징 방식의 원리는 전체 데이터를 읽은 뒤, 처음부터 지정된 오프셋까지 찾아 떠납니다. 만약 도큐멘트 수가 1억 건이고 skip이 2천만이면, 첫 번째 문서부터 2천만번째까지 탐색을 하는 것이지요. 따라서 문서가 많아질 수록 성능 저하가 발생할수밖에 없었습니다.

해결책: _id

// first row
collection.find().limit(pageSize);

// next row
users = collection.find({'_id': {$gt: last_id}}).limit(pageSize);

MongoDB의 모든 도큐멘트에는 고유 키인 _id가 존재합니다. 기본적으로 인덱스가 적용되어 있으며, 페이징을 하기 위한 방법으로 _id를 활용할 수가 있습니다.
페이지를 가져온 뒤, 다음 페이지를 조회하기 위해 해당 페이지 마지막 데이터의 _id 보다 큰 도큐멘트를 가져오는 것입니다.

위 방법으로 페이징에 더는 지연이 발생하지 않았습니다. 만약 순차적 페이징, 도큐멘트 양이 방대해질 수 있다면 위 방법으로 미리 디자인하는 것을 권장합니다.

Reference

https://stackoverflow.com/questions/50260384/what-is-the-best-way-for-pagination-on-mongodb-using-java

댓글
링크
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday