본문으로 바로가기

MS-SQL 2012 이전 (11.X 미만)

예전의 MS-SQL (2012 이전)에서는 페이징 쿼리를 하기 위해서는
보통 ROW_NUMBER() 를 사용하여 정렬순으로 번호를 부여한 다음
중첩 쿼리을 이용하여 정렬번호를 기준으로 페이지에 해당하는 글을 불러오는 방법을 주로 썼습니다.

# ROW_NUMBER() + 중첩 쿼리를 이용한 기존 방식
SELECT T.MEMBER_ID
  FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY MEMBER_ID) AS ROWNUM,
               MEMBER_ID
          FROM MEMBER_TABLE WITH (NOLOCK)
       ) T
 WHERE T.ROWNUM BETWEEN ({pageNo} - 1) * {pageSize} + 1 AND {pageNo} * {pageSize}

위 쿼리에서 MEM_ID로 우선 정렬한 후 ROW_NUMBER()를 이용해 ROWNUM을 부여하고,
BETWEEN 등을 사용하여 탐색하려는 페이지의 첫 번째 ROWNUM부터 페이지의 마지막 ROWNUM 사이를 가져오는 식으로
탐색했습니다.

# 페이지 당 10개 씩 가져올 때
# 1페이지
SELECT T.MEMBER_ID
  FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY MEMBER_ID) AS ROWNUM,
               MEMBER_ID
          FROM MEMBER_TABLE WITH (NOLOCK)
       ) T
 WHERE T.ROWNUM BETWEEN 1 AND 10
 
# 5페이지
SELECT T.MEMBER_ID
  FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY MEMBER_ID) AS ROWNUM,
               MEMBER_ID
          FROM MEMBER_TABLE WITH (NOLOCK)
       ) T
 WHERE T.ROWNUM BETWEEN 41 AND 50

 

MS-SQL 2012 이후 (11.X 이상)

MS-SQL 2012 이후에 추가된 ORDER BY 절의 OFFSET - FETCH 문을 통해
중첩 쿼리 없이 한 번에 가져올 수 있습니다.

# 양식
ORDER BY {정렬 대상 컬럼}
    OFFSET {건너 뛸 행의 수} ROWS
    FETCH NEXT {가져올 행의 수} ROWS ONLY

ORDER BY를 통해 정렬 기준을 정한 뒤
OFFSET을 통해 건너 뛸 행의 수를 먼저 설정하고
(1부터 가져올 경우 OFFSET 0 ROWS, 11부터 가져올 경우 OFFSET 10 ROWS)

FETCH NEXT 에서 몇 개의 행을 가져올 지 결정하게 됩니다.
(한 페이지 내에 10개를 가져올 경우 FETCH NEXT 10 ROWS ONLY)

# OFFSET - FETCH 를 사용한 예
SELECT MEMBER_ID
  FROM MEMBER_TABLE WITH (NOLOCK)
 ORDER BY MEMBER_ID
       OFFSET ({pageNo} - 1) * {pageSize} ROWS
       FETCH NEXT {pageSize} ROWS ONLY
       
# 1페이지
SELECT MEMBER_ID
  FROM MEMBER_TABLE WITH (NOLOCK)
 ORDER BY MEMBER_ID
       OFFSET 0 ROWS
       FETCH NEXT 10 ROWS ONLY
       
# 5페이지
SELECT MEMBER_ID
  FROM MEMBER_TABLE WITH (NOLOCK)
 ORDER BY MEMBER_ID
       OFFSET 40 ROWS
       FETCH NEXT 10 ROWS ONLY       

 

중첩 쿼리를 쓰지 않아서 실행계획도 훨씬 간단해집니다.

그림 1) ROW_NUMBER() + 중첩쿼리 사용한 경우 실행 계획

 

 

 

그림 2) OFFSET - FETCH 적용하여 단일 쿼리로 수행한 경우 실행 계획

 

 

 

쿼리도 간단해지고 성능 상의 이점도 가질 수 있습니다.

출처: https://www.hyoyoung.net/104 [Yes, I am YOUNG.:티스토리]

'Database > MSSQL' 카테고리의 다른 글

[MSSQL] DB 백업/복원 시 오류 메시지 발생  (0) 2023.10.05
[MSSQL] 기간을 기간으로 조회  (0) 2021.08.23
[MSSQL] SET XACT_ABORT 정의  (0) 2021.02.02
[MSSQL] SET NOCOUNT 정의  (0) 2021.02.02
[MSSQL] 문자열 함수 STR  (0) 2020.01.09