본문 바로가기
개발일지/postgresql

Offset과 Limit

2024. 7. 22.

OFFSET과 LIMIT은 SQL 쿼리에서 페이징(paging)을 구현할 때 자주 사용하는 문법이다. 하지만 이들이 성능에 미치는 영향에 대해 이해하는 것이 중요하다. 다음은 OFFSET과 LIMIT을 사용했을 때 성능에 미칠 수 있는 영향이다.

1. 큰 OFFSET 값의 성능 문제

OFFSET은 결과 집합의 처음부터 지정된 수만큼의 행을 건너뛰기 위해 사용된다. 그러나 이 작업은 단순히 건너뛰는 것처럼 보이지만, 실제로는 데이터베이스가 OFFSET 이전의 모든 행을 여전히 읽어야 한다. 이 때문에 OFFSET 값이 클수록 성능이 저하될 수 있다.

예를 들어, 다음과 같은 쿼리가 있다고 가정해보자

SELECT id, data_value FROM tb_n_machine1 
ORDER BY id OFFSET 100000 LIMIT 10;
 

이 경우 데이터베이스는 먼저 id 기준으로 정렬된 100,000개의 행을 읽고, 그 후에 10개의 행을 반환한다. 이 과정에서 100,000개의 행을 건너뛰기 위해 데이터베이스는 여전히 모든 데이터를 스캔해야 하므로 OFFSET 값이 커질수록 쿼리 성능이 떨어질 수 있다.

 

2. 인덱스 사용의 중요성

OFFSET과 LIMIT이 사용된 쿼리에서 성능을 향상시키기 위해서는 적절한 인덱스를 사용하는 것이 매우 중요하다. 인덱스가 제대로 설정되지 않으면 데이터베이스는 ORDER BY와 함께 사용하는 열을 정렬하기 위해 테이블 스캔을 수행할 수 있다. 인덱스는 이러한 작업을 최적화하여 쿼리 속도를 높일 수 있습니다.

예를 들어, 위 쿼리에서 id 열에 인덱스가 있는 경우, 데이터베이스는 인덱스를 사용하여 더 효율적으로 OFFSET과 LIMIT을 적용할 수 있다.

 

3. 대안 전략: Key-based Pagination

큰 OFFSET 값을 피하기 위해 Key-based Pagination 또는 Seek Method라 불리는 방법을 사용할 수 있다. 이 방법은 특정 키(예: id 컬럼)의 값을 기준으로 페이지를 가져오는 방식이다. 이 방식은 OFFSET을 사용할 때 발생할 수 있는 성능 문제를 피할 수 있다.

예를 들어, 다음과 같이 id 값을 기준으로 페이징할 수 있다.

SELECT id, data_value FROM tb_n_machine1
WHERE id > 100000
ORDER BY id
LIMIT 10;
-- 이전 페이지의 마지막 ID를 사용 ORDER BY id LIMIT 10;
  • 이전 페이지의 마지막 id를 기준으로 다음 페이지를 가져온다.
  • 데이터 정렬이 일정하다는 가정 하에, 불필요한 스캔을 피하고 OFFSET 없이 필요한 데이터만 가져온다.

이 방식은 앞서 읽어온 행들을 다시 계산하지 않으므로, 성능적으로 더 우수할 수 있다.

 

단점은

  • 전 페이지의 마지막 id를 클라이언트가 유지해야 한다.
  • id 필드가 고유해야 하고, 순차적인 정렬이 가능해야 한다.

 

 

4. 결론

  • OFFSET은 페이징을 구현하는 데 유용하지만, 큰 값의 OFFSET을 사용할 경우 성능이 저하될 수 있다.
  • LIMIT은 결과 집합의 크기를 제한하는 데 유용하지만, OFFSET과 결합할 때 성능 문제가 발생할 수 있다.
  • 적절한 인덱스 설정과 Key-based Pagination과 같은 대체 방법을 고려하여 성능 문제를 완화할 수 있다.

따라서, OFFSET과 LIMIT을 사용할 때는 쿼리의 성능을 고려하고, 데이터 크기가 큰 경우 대체 전략을 사용하는 것이 좋다.