컴퓨터일반/DB

[MSSQL] 대용량 데이터 페이징 처리 성능 최적화 가이드

G-Ryon 2026. 3. 26. 13:47

데이터베이스의 규모가 커질수록 SELECT *로 모든 데이터를 가져오는 것은 불가능에 가깝습니다.

수백만 건의 데이터 중 사용자가 보고 있는 10~20건만 효율적으로 골라내는 MSSQL 페이징 기법 3가지를 소개합니다.

1. OFFSET-FETCH (SQL Server 2012 이상 권장)

ANSI 표준이며 현재 MSSQL에서 가장 권장되는 방식입니다. 구문이 직관적이고 가독성이 매우 높습니다.

  • 특징: 반드시 ORDER BY 절과 함께 사용해야 합니다.
  • 장점: 코드가 간결하며 유지보수가 쉽습니다.
SQL
 
-- 11번째부터 10개의 행을 가져오는 예시 (Page 2)
SELECT *
FROM Orders
ORDER BY OrderDate DESC, OrderID ASC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

2. ROW_NUMBER() 함수 활용 (전통적 방식)

OFFSET-FETCH가 도입되기 전 가장 많이 사용되던 방식입니다. 서브쿼리를 사용하여 순번을 매긴 뒤 범위를 필터링합니다.

  • 특징: OVER(ORDER BY ...)를 통해 정렬 기준을 정의합니다.
  • 장점: 복잡한 조건부 페이징이나 하위 버전(2005, 2008)과의 호환성이 좋습니다.
SQL
 
SELECT * FROM (
    SELECT *, ROW_NUMBER() OVER (ORDER BY OrderDate DESC) AS RowNum
    FROM Orders
) AS PageResults
WHERE RowNum BETWEEN 11 AND 20;

3. TOP과 NOT IN을 이용한 방식 (구형/비권장)

아주 오래된 방식이지만 간혹 레거시 코드에서 볼 수 있습니다. 앞선 10개를 제외한 나머지 중 상위 10개를 가져오는 식입니다.

  • 단점: 데이터량이 많아질수록 NOT IN 내부의 스캔 비용이 기하급수적으로 늘어나 성능이 가장 좋지 않습니다.
SQL
 
-- 비권장 방식
SELECT TOP 10 * FROM Orders
WHERE OrderID NOT IN (SELECT TOP 10 OrderID FROM Orders ORDER BY OrderDate DESC)
ORDER BY OrderDate DESC;

🚀 대용량 처리 시 '진짜' 중요한 성능 포인트

단순히 문법만 바꾼다고 속도가 빨라지지 않습니다. MSSQL 엔진이 데이터를 찾는 방식을 이해해야 합니다.

  1. 인덱스 검색 (Index Seek) 유도:
  2. 페이징의 기준이 되는 ORDER BY 컬럼은 반드시 인덱스가 걸려 있어야 합니다.
    인덱스가 없다면 전체 데이터를 정렬(Sort)하는 부하가 발생하여 페이징의 의미가 퇴색됩니다.
  3. 커서 기반 페이징 (Seek Method):
    • 예: WHERE ID < @LastSeenID ORDER BY ID DESC
  4. OFFSET 값이 커질수록(예: 1,000,000번째 페이지) DB는 앞의 백만 개를 읽어서 버려야 하므로 느려집니다.
    이때는 마지막으로 읽은 고유값(예: ID)을 조건문에 넣는 방식이 가장 빠릅니다.
  5. 포함된 열(Included Columns):
  6. SELECT * 대신 필요한 컬럼만 조회하고, 해당 컬럼들을 인덱스에 포함(INCLUDE)시키면 테이블 자체에 접근하지 않고 인덱스만으로 데이터를 반환하는 '커버링 인덱스' 효과를 볼 수 있습니다.

💡 요약 및 결론

방식 추천 버전 성능 가독성
OFFSET-FETCH 2012+ 우수 최상
ROW_NUMBER() 2005+ 우수 보통
Seek Method 공통 최상 낮음 (로직 복잡)

최신 프로젝트라면 OFFSET-FETCH를 기본으로 사용하되, 초대용량 테이블에서 뒷페이지 조회 성능이 떨어진다면 Seek Method(ID 기반 조건문) 도입을 검토하세요.


Copyright 2026. [버미] all rights reserved.