SERVER/DB

[MSSQL] 게시판 paging를 처리하는 방법 3가지

eunoia07 2022. 1. 26. 14:20

1. paging에 필요한 필수 조건


1. 한 페이지에 출력될 게시물 수

2. 한 화면에 출력된 페이지 수

3. 현재 페이지 번호

 

게시판 페이징을 위해선 이렇게 세 조건이 필요합니다.

2. paging를 처리하는 방법 3가지


  - ROW_NUMBER() OVER()

  - TOP (NOT IN)

  - OFFSET ROWS FETCH NEXT

 

[1. ROW_NUMBER() OVER()]

ROW_NUMBER 함수를 통해 결과물에 순차적으로 번호를 달아주어 조건으로 필요한 부분만 가져와 페이지에 출력하는 방식입니다.

장점 각 행에 번호를 부여하기 때문에 특정 범위의 행 번호 검색이 가능합니다.
단점 게시물 마다 번호를 달아주는것에 대한 시스템의 부하와, 중첩 쿼리 사용으로 인해 속도가 느립니다.
--10에서 20까지 가져오는 쿼리입니다.
SELECT * 
FROM 
(
  SELECT ROW_NUMBER() OVER(ORDER BY A.id ASC) AS ROWNUM,
  A.*
  FROM TABLE A WITH(NOLOCK)
)B
WHERE B.ROWNUM BETWEEN 10 AND 20;


-- @PAGE_NO : 현재 페이지 번호
-- @PAGE_ROW : 한 페이지에 출력될 게시물 수
SELECT * 
FROM 
(
  SELECT ROW_NUMBER() OVER(ORDER BY A.id ASC) AS ROWNUM,
  A.*
  FROM TABLE A WITH(NOLOCK)
)B
WHERE B.ROWNUM BETWEEN (@PAGE_NO-1)*@PAGE_ROW AND @PAGE_NO*@PAGE_ROW;

 

[2. TOP (NOT IN)]

NOT IN 구문을 이용해 필요 없는 값을 먼저 제외하고 나머지 데이터에서 TOP을 쿼리하는 방식입니다.

장점 유지보수가 간편하고 가장 간결한 페이징 쿼리가 가능합니다. 또한, 페이지 수가 적을 때 속도가 빠릅니다.
단점 데이터 양이 많아질수록 성능이 좋지 않고 DB에 부하와, 중첩 쿼리 사용으로 인해 속도가 느립니다.
--10에서 20까지 가져오는 쿼리입니다.
SELECT TOP 10 * 
FROM TABLE A WITH(NOLOCK)
WHERE id NOT IN
(
	SELECT TOP 10 id
  FROM TABLE
  ORDER BY id
)
ORDER BY id

-- @PAGE_NO : 현재 페이지 번호
-- @PAGE_ROW : 한 페이지에 출력될 게시물 수
SELECT TOP @PAGE_ROW * 
FROM TABLE A WITH(NOLOCK)
WHERE id NOT IN
(
  SELECT TOP ((@PAGE_NO-1)*@PAGE_ROW) id
  FROM TABLE
  ORDER BY id
)
ORDER BY id

 

[3. OFFSET ROWS FETCH NEXT]

ORDER BY로 정렬기준을 정하고 OFFSET을 통해 페이징을 할 때마다 건너뛸 행의 수를 설정하고 FETCH를 통해 몇 개의 행을 가져올지 결정하는 방식입니다.

장점 빠르고 간편하게 페이징을 구현할 수 있고 페이지수가 많을 때 속도가 가장 빠릅니다.
단점 같은 쿼리 식에서 TOP, OVER 등 특정 구문을 OFFSET FETCH와 결합해 사용할 수 없습니다.
--10에서 20까지 가져오는 쿼리입니다.
--OFFSET : 10개를 건너뛰고
--FETCH : 10개씩 가져오기
SELECT * 
FROM TABLE A WITH(NOLOCK)
ORDER BY id ASC
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;

-- @PAGE_NO : 현재 페이지 번호
-- @PAGE_ROW : 한 페이지에 출력될 게시물 수

SELECT * 
FROM TABLE A WITH(NOLOCK)
ORDER BY id ASC
OFFSET (@PAGE_NO-1)*@PAGE_ROW ROWS
FETCH NEXT @PAGE_ROW ROWS ONLY;

TOP과 유사하지만, 필터를 수행하기 전 몇 개의 ROW를 건널 뛸지 표현이 가능하기에 TOP 보다 데이터 양이 많을 때 빠릅니다.

 

3. 실행 계획


[1. ROW_NUMBER() OVER()]

 

[2. TOP (NOT IN)]

[3. OFFSET ROWS FETCH NEXT]