데이터베이스 페이징 성능을 어떻게 봐야 하는가
페이징은 왜 느려지는가
목록 조회에서 페이지네이션은 당연한 기능처럼 보이지만, 데이터가 커질수록 단순 limit offset 방식이 병목이 되기 쉽다.
문제는 DB가 offset = 100000이라고 해서 100000개를 건너뛰는 비용이 공짜가 아니라는 점이다. 보통은 앞 데이터를 훑은 뒤 버리는 식으로 처리되기 때문에 뒤 페이지로 갈수록 느려질 수 있다.
Offset 기반 페이징
장점:
- 구현이 단순하다.
- 특정 페이지로 바로 이동하기 쉽다.
단점:
- 뒤 페이지일수록 비용이 커진다.
- 중간에 데이터가 삽입/삭제되면 결과가 흔들릴 수 있다.
Cursor 기반 페이징
이전 페이지의 마지막 키를 기준으로 다음 페이지를 가져오는 방식이다.
장점:
- 대량 데이터에서 안정적이다.
- 무한 스크롤과 잘 맞는다.
단점:
- 임의 페이지 이동은 어렵다.
- 정렬 기준이 명확해야 한다.
성능을 볼 때 체크할 것
- 정렬 기준 컬럼에 인덱스가 있는가
- count 쿼리가 비싸지 않은가
- 조회 쿼리와 count 쿼리를 분리해야 하는가
- tie-breaker가 있는가
예를 들어 created_at desc만 쓰면 같은 시간대 레코드에서 순서가 흔들릴 수 있어서 created_at desc, id desc처럼 보조 정렬 키를 두는 편이 안전하다.
흔한 실수
- 무조건
Page를 반환해서 무거운 count 쿼리를 매번 수행함 - fetch join과 페이징을 함께 써서 예상과 다른 결과가 나옴
- offset 방식이 느린데도 쿼리 대신 애플리케이션 레이어만 만짐
정리
페이징 성능은 “API 모양”보다 “DB가 어떤 순서로 몇 건을 읽는가”의 문제다. 데이터가 커지면 결국 offset과 cursor 중 어떤 방식을 택할지, 그리고 정렬/인덱스를 어떻게 맞출지가 핵심이 된다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.
댓글
아직 댓글이 없습니다