'mssql 페이징'에 해당되는 글 2건

mssql 페이징2

개발/MS-SQL 2013. 1. 22. 15:37

1. 유명한 NOT IN 기법.

초반 페이지는 큰 문제가 없으나, 뒤쪽으로 갈수록 많은 데이터를 NOT IN 처리 해야 하기때문에 문제가 많아진다.

SELECT TOP (@PAGESIZE) SEQ, THREAD, DEPTH, WRITER, TITLE, READCOUNT, WRITEDATE FROM BLUE_BOARD
WHERE THREAD NOT IN
(SELECT TOP (@PAGESIZE * (@PAGE-1)) THREAD FROM BLUE_BOARD ORDER BY THREAD DESC)
ORDER BY THREAD DESC

기본형태

첫페이지 끝페이지(50000)

4 ????(엄청나게 느림)

검색과 정렬 추가시

첫페이지 끝페이지(50000)

50 35000

정적으로 검색,정렬 하였을때

첫페이지 끝페이지

10 8000 (검색실패시 3000)

글을 수정하였다 역시 잘못되었다.

무지무지무지 느리다.

----------> 해당 쿼리를 동적. 쿼리로 제작하였을 경우 마지막 페이지가 1초가 걸리는 괴?상한 현상이 계속 목격되고 있다.

----------> 검색시 4초 가량이 소요되었고 검색 실패시에도 2초 가량이 소요되었다 -----> 동적쿼리는 일반적으론 나쁘다고 하는데(물론 좋은 경우도 있겠지만) 100만건 기준으로 정말로 1~2초라면.... 사용해도 되지 않을까

2. IN 기법.

NOT IN의 문제를 개선했다고 한다.

하지만 역시나 후반페이지에 문제가 많다고 한다. 테스트 해보진 않았다.


3. MIN 기법

MIN을 이용한 기법.

SELECT TOP (@PAGESIZE) SEQ, THREAD, DEPTH, WRITER, TITLE, READCOUNT, WRITEDATE
FROM BLUE_BOARD
WHERE THREAD <=
(
SELECT MIN(THREAD)
FROM
(
SELECT TOP (((@page-1)*20)+1) THREAD
FROM BLUE_BOARD
ORDER BY THREAD DESC
) AS A
)
ORDER BY THREAD DESC

기본형태

첫페이지 끝페이지(50000)

5 200

검색과 정렬 추가시엔 테스트를 해보지 않았다.

4. 인덱스를 이용한 기법

빠르다고 한다. 그러나 페이징의 헛점이 많다고 한다.

5. ROW_NUMBER()를 이용한 기법중. 하나

2005부터 사용 가능하다.

특이사항으로는 총 카운트 T2.CNT 와, 라스트페이지를 CEILING(T2.CNT/@PAGESIZE) AS 'LASTPAGE'

테이블에 같이 집어넣는다는것이다. 좀더 개선할수 있을듯 하다.

속도는 좋을것같아 보인다.

SELECT * FROM
(
SELECT
(
ROW_NUMBER() OVER(ORDER BY THREAD DESC)
) AS ROWNUM,*
FROM BLUE_BOARD
) AS A
WHERE A.ROWNUM BETWEEN ((@PAGE-1)*@PAGESIZE)+1 AND @PAGE*@PAGESIZE

기본형태

첫페이지 끝페이지

5 1400

검색과 정렬 추가시

첫페이지 끝페이지

80000 80000

유명한 ROWNUM 기법 치고는 생각보다 느리다. 어째성?;;;;

뭐지? 내 테스트 쿼리가 잘못된것인가? ㅋㅋㅋㅋㅋ

정적으로 검색,정렬 하였을때

첫페이지 끝페이지

8000 12000 (검색 실패시 3000)

정도가 소요되었다.

생각보다 안좋다-_-;

6. MAX,MIN 조합기법

위의 3번 쿼리인 MIN쿼리와 흡사하다

해당 방법은 쿼리가 길다는 문제이다.(쿼리가 복잡해지면 아래 쿼리도 그만큼 복잡해진다)

DECLARE @MAXCNT INT
,@MINCNT INT


SELECT @MINCNT = (ISNULL(MIN(THREAD),0)),
@MAXCNT = (ISNULL(MAX(THREAD),0))
FROM
(
SELECT TOP(@PAGE * @PAGESIZE) THREAD
FROM BLUE_BOARD
ORDER BY THREAD DESC
) T


SELECT @MAXCNT = MIN(THREAD)
FROM
(
SELECT TOP(((@PAGE-1)*@PAGESIZE)+1) THREAD
FROM BLUE_BOARD
WHERE THREAD BETWEEN @MINCNT AND @MAXCNT
ORDER BY THREAD DESC
) T


SELECT TOP(@PAGESIZE) * FROM BLUE_BOARD
WHERE THREAD BETWEEN @MINCNT AND @MAXCNT
ORDER BY THREAD DESC

기본형태

첫페이지 끝페이지(50000)

10 290

꽤나 빠른데? 하지만 검색과 정렬을 넣는다면 좀 복잡해지는 단점이....

7. SELECT TOP 11 * BLUE_BOARD WHERE ID <= 마지막 번호 (ORDER BY DESC)

페이징이라고 하기엔 약간 꼼수?틱한 방법인데

TOP 11은 사실 글을 10개만 보여주는것이다 그리고 1은 다음 페이지의 첫 결과가 되는것이다

계속 11개씩 불러서 10개만 페이지에 뿌려주는 ㅎㅎㅎ

SELECT TOP 11 * FROM BLUE_BOARD ORDER BY THREAD DESC
SELECT TOP 11 * FROM BLUE_BOARD WHERE SEQ <= 11 ORDER BY THREAD DESC

동접사수 많고 글수가 어마어마 하다면 이방법이 제일일듯 하다.

그러나 이전페이지는... 어떻게 구현을 해야할지

8. CTE

이녀석도 결국은 ROW_NUMBER를 의존하는데

일종의 뷰? 같은것을 생성하여 그것으로 페이징한다고 생각하면 될듯하다.(물론 이게 아니지만...)

Set nocount on을 빼먹으면 아예 작동조차 하지 않는다 와이?

SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

WITH PAGELIST AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY THREAD DESC) AS ROWNUM
FROM BLUE_BOARD
)
SELECT * FROM PAGELIST
WHERE ROWNUM BETWEEN ((@PAGE-1)*@PAGESIZE)+1 AND @PAGE*@PAGESIZE

기본형태

첫페이지 끝페이지

2 1300

검색과 정렬 추가시

첫페이지 끝페이지

63000 ????

정적 검색과 정렬 추가시

첫페이지 끝페이지

1000 12000

별다른 조건이 없었을때는 제법 나쁘지 않은듯 싶다

'개발 > MS-SQL' 카테고리의 다른 글

mssql 스키마 변경(테이블 전체)  (0) 2014.02.18
mssql cursor  (0) 2013.06.10
asp mssql 페이징  (0) 2013.01.22
mssql IDENTITY 증가값 초기화  (0) 2012.10.30
Mssql identity 설정 on/off  (0) 2012.10.25
블로그 이미지

쭈니후니

개발자로서 공부와 낚시를 좋아하는 한사람으로서의 추억을 담을 블로그입니다.

,

asp mssql 페이징

개발/MS-SQL 2013. 1. 22. 14:54

// 총 개수 - 리스트 쿼리

SQL = "SELECT count(*) as recordCount FROM HPA010T "
SQL = SQL & " WHERE SEQ IS NOT NULL "

Set rs = dbCon.Execute(SQL)
'// 총 레코드 갯수
li_totalCnt = FormatNumber(rs("recordCount"), 0)

'// 한 페이지 표시 레코드 수
li_recordCnt = 10

'// 총 페이지 갯수
li_pageCnt = int((li_totalCnt-1)/li_recordCnt) + 1

'// 페이지 번호 - movePage를 get으로 받아온다
li_movePage = Request.QueryString("movePage")

'//2005 이후 버전에서만 RowNum 를 지원함
SQL = ""
SQL = SQL & " SELECT SEQ "
SQL = SQL & " ,USE_YN "
SQL = SQL & " ,TITLE "
SQL = SQL & " ,START_DT "
SQL = SQL & " ,END_DT "
SQL = SQL & " ,KIND_TP "
SQL = SQL & " ,POPUP_TP "
SQL = SQL & " ,INSERT_DT "
SQL = SQL & " FROM (SELECT ROW_NUMBER() OVER (ORDER BY INSERT_DT DESC) AS RowNum "
SQL = SQL & " ,SEQ "
SQL = SQL & " ,USE_YN "
SQL = SQL & " ,TITLE "
SQL = SQL & " ,START_DT "
SQL = SQL & " ,END_DT "
SQL = SQL & " ,KIND_TP "
SQL = SQL & " ,POPUP_TP "
SQL = SQL & " ,INSERT_DT "
SQL = SQL & " FROM HPA010T "
SQL = SQL & " ) AS K "
SQL = SQL & " WHERE RowNum BETWEEN "& ((li_movePage - 1) * li_recordCnt) + 1 & "
SQL = SQL & " AND " & ((li_movePage - 1) * li_recordCnt) + li_recordCnt

<설명>
1. from절 : 가져오려는 orderby 로 row번호를 붙여 select한다.
2. 1에서 가져온 테이블에서 RowNum 에 범위를 주어 원하는 범위의 데이터만 가져온다.
예) 1페이지당 10개씩 보여준다고 할때 3페이지의 리스트를 가져올 경우 시작번호는 21, 끝번호는 30가 된다.



'//2000이하버전에서는 RowNum를 지원하지 않기때문에 유일한 키를 갖고 페이징처리함.

'//**()안과 바깥에 조건이 같아야 함**
SQL = ""
SQL = SQL & " SELECT TOP " & li_recordCnt & "
SQL = SQL & " SEQ "
SQL = SQL & " ,USE_YN "
SQL = SQL & " ,TITLE "
SQL = SQL & " ,START_DT "
SQL = SQL & " ,END_DT "
SQL = SQL & " ,KIND_TP "
SQL = SQL & " ,POPUP_TP "
SQL = SQL & " ,INSERT_DT "
SQL = SQL & " FROM HPA010T "
SQL = SQL & " WHERE SEQ NOT IN "
SQL = SQL & " (SELECT TOP " & ((li_movePage - 1) * li_recordCnt) & " SEQ "
SQL = SQL & " FROM HPA010T "
SQL = SQL & " WHERE SEQ IS NOT NULL "
SQL = SQL & " ORDER BY INSERT_DT DESC ) "
SQL = SQL & " ORDER BY INSERT_DT DESC "

<설명> - 1페이지당 10개씩 보여준다고 할때 3페이지의 리스트를 가져올 경우
1. 조건 : 데이터의 유일한 키가 되는 값이 있어야 한다. WHERE 절 안과 밖 select 의 ORDER BY가 같아야 한다.
2. 원하는 orderby로 TOP 30 개를 select 한다.
3. 같은 orderby로 TOP 20 개를 select 한다.
4. 2에서 3을 뺀다. (여기서는 NOT IN을 사용) - 이 작업이 정확히 이뤄질려면 유일한 키로 NOT IN 처리 해야한다.

 

출처 : http://coolmsd.tistory.com/70 

'개발 > MS-SQL' 카테고리의 다른 글

mssql cursor  (0) 2013.06.10
mssql 페이징2  (0) 2013.01.22
mssql IDENTITY 증가값 초기화  (0) 2012.10.30
Mssql identity 설정 on/off  (0) 2012.10.25
sp_dbcmptlevel 호환성 수준  (0) 2012.04.17
블로그 이미지

쭈니후니

개발자로서 공부와 낚시를 좋아하는 한사람으로서의 추억을 담을 블로그입니다.

,