Pleasure resort of Gleam™

While Loop를 사용하는 아래와 같은 쿼리가 있다.
(원래 Cursor를 사용 하던 쿼리였다.)
     SET NOCOUNT ON;
    SET XACT_ABORT ON;

    BEGIN TRAN                                                                              -- 트랜잭션 시작

    DECLARE @RegUser                 CHAR(8)
        SET @RegUser='20070073'

    DECLARE @iCnt                   INT             -- Loop 변수
          , @iTotalCnt              INT             -- 전체 데이터 수
          , @sPrevColGrp            VARCHAR(30)
     SELECT @iCnt=0, @iTotalCnt=0, @sPrevColGrp=''

    -- 임시 테이블 선언
    DECLARE @tbTmp TABLE (
        Idx                         INT             IDENTITY(1,1)
       ,ColGrp                      INT
       ,Col01                       VARCHAR(30)
       ,Col02                       VARCHAR(30)
       ,Col03                       VARCHAR(30)
       ,RegDate                     DATETIME        DEFAULT(GETDATE())
    )
    DECLARE @tbTmp2 TABLE (
        ColGrp                     INT
       ,ColGrpSeq                  INT
       ,RegDate                    DATETIME        DEFAULT(GETDATE())
    )

    INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq) VALUES ('1', 5477)
    INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq) VALUES ('2', 8901)
    INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq) VALUES ('3', 9901)



    INSERT INTO @tbTmp (ColGrp, Col01, Col02, Col03)
    SELECT *
      FROM (
            SELECT '1' AS ColGrp, 'Col01_1' AS Col01, '' AS Col02, '' AS Col03
            UNION
            SELECT '2' AS ColGrp, 'Col01_2' AS Col01, '' AS Col02, '' AS Col03
            UNION
            SELECT '2' AS ColGrp, 'Col01_3' AS Col01, '' AS Col02, '' AS Col03
            UNION
            SELECT '3' AS ColGrp, 'Col01_4' AS Col01, '' AS Col02, '' AS Col03
            UNION
            SELECT '3' AS ColGrp, 'Col01_5' AS Col01, '' AS Col02, '' AS Col03
           ) A

    SELECT @iTotalCnt=COUNT(*) FROM @tbTmp                                                  -- 선택된 항목의 COUNT

    WHILE (@iTotalCnt>@iCnt)                                                                -- Loop 시작
    BEGIN
        SET @iCnt = @iCnt+1                                                                 -- Loop count 증가
        PRINT ('@iTotalCnt is ' + CAST(@iTotalCnt AS VARCHAR) + ', @iCnt is ' + CAST(@iCnt AS VARCHAR))

        IF (((SELECT ColGrp FROM @tbTmp WHERE Idx=@iCnt) <> @sPrevColGrp) OR (@sPrevColGrp = ''))
        BEGIN
            SELECT @sPrevColGrp = ColGrp FROM @tbTmp WHERE Idx=@iCnt

                INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq)
                SELECT A.ColGrp, (MAX(B.ColGrpSeq)+1) AS ColGrpSeq
                  FROM @tbTmp A
                  JOIN @tbTmp2 B
                    ON A.ColGrp = B.ColGrp
                 WHERE A.Idx =@iCnt
              GROUP BY A.ColGrp


            UPDATE @tbTmp
               SET Col02 =  A.Col01 + '_' + CAST(ISNULL( (SELECT MAX(ColGrpSeq) FROM @tbTmp2 WHERE ColGrp = A.ColGrp) , 1) AS VARCHAR)
              FROM @tbTmp A
             WHERE A.Idx>=@iCnt
        END

        UPDATE @tbTmp
           SET Col03 = (
                    A.Col01 + '_' + Col02 +'_' + CAST(Idx AS VARCHAR)
               )
          FROM @tbTmp A
         WHERE A.Idx=@iCnt
    END

    SELECT * FROM @tbTmp
    SELECT * FROM @tbTmp2
    ROLLBACK TRAN

원본 쿼리 실행 결과

원본 쿼리 실행 결과

원본 쿼리 통계

원본 쿼리 통계


이 쿼리에서 Loop를 제거하고 아래와 같이 만들었다.
    SET NOCOUNT ON;
    SET XACT_ABORT ON;
    BEGIN TRAN

    DECLARE @RegUser                 CHAR(8)
        SET @RegUser='20070073'

    DECLARE @iCnt                   INT             -- Loop 변수
          , @iTotalCnt              INT             -- 전체 데이터 수
          , @sPrevColGrp            VARCHAR(30)
     SELECT @iCnt=0, @iTotalCnt=0, @sPrevColGrp=''

    -- 임시 테이블 선언
    DECLARE @tbTmp TABLE (
        Idx                         INT             IDENTITY(1,1)
       ,ColGrp                      INT
       ,Col01                       VARCHAR(30)
       ,Col02                       VARCHAR(30)
       ,Col03                       VARCHAR(30)
       ,RegDate                     DATETIME        DEFAULT(GETDATE())
    )
    DECLARE @tbTmp2 TABLE (
        ColGrp                     INT
       ,ColGrpSeq                  INT
       ,RegDate                    DATETIME        DEFAULT(GETDATE())
    )

        INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq) VALUES ('1', 5477)
        INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq) VALUES ('2', 8901)
        INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq) VALUES ('3', 9901)



        INSERT INTO @tbTmp (ColGrp, Col01, Col02, Col03)
        SELECT *
          FROM (
                SELECT '1' AS ColGrp, 'Col01_1' AS Col01, '' AS Col02, '' AS Col03
                UNION
                SELECT '2' AS ColGrp, 'Col01_2' AS Col01, '' AS Col02, '' AS Col03
                UNION
                SELECT '2' AS ColGrp, 'Col01_3' AS Col01, '' AS Col02, '' AS Col03
                UNION
                SELECT '3' AS ColGrp, 'Col01_4' AS Col01, '' AS Col02, '' AS Col03
                UNION
                SELECT '3' AS ColGrp, 'Col01_5' AS Col01, '' AS Col02, '' AS Col03
               ) A

        SELECT @iTotalCnt=COUNT(*) FROM @tbTmp                                                  -- 선택된 항목의 COUNT

        INSERT INTO @tbTmp2 (ColGrp, ColGrpSeq)
        SELECT A.ColGrp, (MAX(B.ColGrpSeq)+1) AS ColGrpSeq
          FROM @tbTmp A
          JOIN @tbTmp2 B
            ON A.ColGrp = B.ColGrp
      GROUP BY A.ColGrp

        UPDATE @tbTmp
           SET Col02 =  A.Col01 + '_' + CAST(ISNULL( (SELECT MAX(ColGrpSeq) FROM @tbTmp2 WHERE ColGrp = A.ColGrp) , 1) AS VARCHAR)
          FROM @tbTmp A
         WHERE A.Idx>=@iCnt

        UPDATE @tbTmp
           SET Col03 = (
                    A.Col01 + '_' + Col02 +'_' + CAST(Idx AS VARCHAR)
               )
          FROM @tbTmp A


        SELECT * FROM @tbTmp
        SELECT * FROM @tbTmp2
    ROLLBACK TRAN


수정된 쿼리 실행 결과

수정된 쿼리 실행 결과

수정된 쿼리 통계

수정된 쿼리 통계



딱 봐도 속도가 많이 빨라졌다...ㅋ

Comment +0

/*
tempdb 데이터베이스 이동
tempdb 데이터베이스의 크기와 물리적인 배치가
시스템의 성능에 영향을 미칠 수 있으므로
tempdb를 확장하거나 이동하는 작업을
수행하는 경우가 종종 발생한다.

다음에 나오는 일련의 작업은 동일한
SQL Server 인스턴스에서 tempdb를
다른 위치로 이동하는 방법을 보여준다.

본 작업은 반드시 서비스가 중지된,
서버 점검 시간에 이루어져야 한다.

화일을 이동하는 위치는
반드시 디스크 드라이브 및 타겟 폴더가 존재해야 한다.
*/
--<<<tempdb를 디스크상의 다른 위치로 이동하기>>>
USE master
GO
--1.tempdb의 논리파일 이름 확인
SELECT name, physical_name, state_desc
  FROM sys.master_files
WHERE database_id = DB_ID(N'tempdb')
GO

--2.ALTER DATABASE 사용하여 파일 위치 변경
ALTER DATABASE tempdb
MODIFY FILE(NAME = tempdev, FILENAME = 'G:\Data\tempdb.mdf')
ALTER DATABASE tempdb
MODIFY FILE(NAME = templog, FILENAME = 'H:\Log\templog.ldf')
GO
--3.SQL Server를 중지하고 다시 시작한다.

--4.SQL Server 서비슥가 시작된것을 확인후, 제대로 이동이 되었는지 확인
SELECT name, physical_name, state_desc
  FROM sys.master_files
WHERE database_id = DB_ID(N'tempdb')
GO
--5.기존 위치에 존재하는 tempdb 파일을 삭제한다.
/*
tempdb는 SQL Server가 재시작할때마다 재생성을 거치므로
기존의 tempdb 파일들을 새로운 위치로 이동할 필요없다.

같은 방법으로 사용자 생성한 Database의 화일들도
이동시킬 수 있으나 사용자가 생성한 Database는
기존화일을 복사하여 새로운 위치에 붙여넣은 후
이동이 끝나면 기존화일을 삭제하여 준다.
*/

from: http://dbmaster.tistory.com/50

Comment +0



Generate random password script for  MS-SQL Server

Comment +0











from: http://www.microsoft.com/korea/sql/prodinfo/SQL2005_Resources.mspx

Comment +0

DATEPART(Quarter, GETDATE())

Example:
DECLARE @Quarter VARCHAR(5)
SET @Quarter = CAST(DATEPART(Year, GETDATE()) AS VARCHAR) + CAST(DATEPART(Quarter, GETDATE()) AS VARCHAR)
SELECT @Quarter AS Q


Ref:
    DATEPART

'Dev & Mng' 카테고리의 다른 글

SQL Server 실전 묻고 답하기  (0) 2008.03.19
Get Quarter in MS-SQL Server  (0) 2008.02.12
Database procedure list in MS-SQL Server  (0) 2008.02.12
Java with UTF-8  (0) 2008.02.12

Comment +0

    SELECT so.name AS SPName,
           so.crdate AS CreateDate
      FROM sysobjects so
     WHERE so.type ='P'
       AND so.name LIKE '%'
  ORDER BY so.name

SP 검색 하다가.....

'Dev & Mng' 카테고리의 다른 글

Get Quarter in MS-SQL Server  (0) 2008.02.12
Database procedure list in MS-SQL Server  (0) 2008.02.12
Java with UTF-8  (0) 2008.02.12
Windows Update Downloader  (0) 2008.02.06

Comment +0

sp_changeobjectowner [ @objname = ] 'object' , [ @newowner = ] 'owner'

인수

[@objname =] 'object'

현재 데이터베이스 안에 있는 기존 테이블, 뷰 또는 저장 프로시저의 이름입니다. objectnvarchar(517)이며, 기본값은 없습니다. objectexisting_owner.object 형식으로 기존 개체 소유자로 한정될 수 있습니다.

[@newowner =] 'owner'

개체의 새 소유자가 될 보안 계정의 이름입니다. ownersysname이며, 기본값은 없습니다. owner는 반드시 현재 데이터베이스 내의 유효한 Microsoft® SQL Server™ 사용자 또는 역할이거나 Microsoft Windows NT® 사용자 또는 그룹이어야 합니다. Windows NT 사용자 또는 그룹을 지정할 경우 sp_grantdbaccess를 사용하여 추가하고 데이터베이스에서 Windows NT 사용자 또는 그룹으로 알고 있는 이름을 지정합니다.

반환 코드 값

0(성공) 또는 1(실패)


http://groups.google.com/groups/search?hl=en&q=sp_changeobjectowner&qt_s=Search

http://sqler.pe.kr/FriendLec/TurtleMa/LecA/a05.asp

'Dev & Mng' 카테고리의 다른 글

SVN Service Wrapper for Windows  (2) 2006.07.30
ms-sql 서버에서 소유자 일괄 변경  (0) 2006.07.20
VS.NET Editor 윈도우에서 컬럼 구분선 보이기  (0) 2006.07.18
ADO Object Referance  (0) 2006.07.13

Comment +0

페이징 테스트
1.Rs.Move() 2.Rs.AbsolutePage 3.Top 20[NOT IN] 4.TOP 20[IN] 5.TOP 20[MIN] 6.TOP 20[INDEX, MIN)
제가 어느 페이징이 제일 빠를까.. 고민 하다가.. 테스트로 만들어 보았습니다.
총.. 6가지..입니다..

간단하게 쿼리를 설명해드리겠습니다.

1. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]

1번 리스트는 이 쿼리 구문을 써서 했고요. 현제 개시물까지 이동을 Rs.Move(이동할수) 로 처리 했습니다.

2. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]    - 1번과 동일

1번과 쿼리구문은 동이하고요. 레코드셋의 AbsolutePage를 이용해서 페이징을 했습니다.

3. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]

  WHERE [글번호필드] NOT IN (SELECT TOP [제거할 게시물수] [글번호필드] FROM [테이블명])
  예전에 태요 사이트에서 보았던 쿼리 구문입니다.. NOT IN 때문에.. 문제시 되었던 쿼리구문이죠.

4. SELECT TOP [불러올 총 게시물수] [출력 필드명] FROM [테이블 명]
  WHERE [글번호] IN (SELECT TOP [페이지출력 갯수] [글번호] FROM
  (SELECT TOP [불러올 총 게시물수] [글번호] FROM [테이블 명]) AS A ORDER BY [글번호])
  ORDER BY [글번호] DESC

  이 쿼리 구문은 3번의 쿼리 구문의 문제점을 보완한 구문입니다. NOT IN 대신에 IN을 사용 했습니다.

5. SELECT TOP [페이지 출력갯수] [출력 필드명] FROM [테이블 명]
  WHERE [글번호] <= (SELECT MIN([글번호])
  FROM (SELECT TOP [제거할 게시물수] + 1 [글번호] FROM [테이블명]) AS A)

  5번째 쿼리 구문은 IN, NOT IN이 아닌 출력할 마지막 글번호 바로 앞이 글번호를 찾아서 처리를 해주는
  쿼리 구문입니다.

6. SELECT TOP [페이지 출력갯수] [출력 필드명] FROM [테이블명]
  WHERE [글번호] <= (SELECT MIN([글번호])
  FROM (SELECT TOP [제거할 게시물수] + 1 [글번호]
  FROM [테이블명] WHERE [인덱스] = [시작인덱스번호] AND [인덱스] = [끝인덱스번호]) AS A
  WHERE [인덱스] = [시작인덱스번호] AND [인덱스] = [끝인덱스번호])
  AND [인덱스] = [시작인덱스번호] AND [인덱스] = [끝인덱스번호]

  6번재 쿼리는.. 글에 인덱스(가칭)라는 필드를 하나 더 추가 해서.. 글 기본 2000개마다 (가변적입니다)
  인덱스를 증가 시켰습니다. 즉 2000개를 하나의 묶음으로 만든것입니다.
  그 인덱스를 기준으로 처리를 해주었습니다.(기본 개념은 영어 사전 입니다 ㅡㅡ;)

위와 같이 간단한 기본 쿼리 구문을 설명? 했습니다.
게시물은 100만개를 넣고 테스트를 했습니다.
테스트 게시판을 보시려면.. 맨위에 각 게시판을 링크를 걸었습니다.
서버가 구려서.. 제대로 될지 모르지만..
제 노트북
(CPU : p4-1.8, RAM : 768Mb, 컴팩 프리자리오 2820AP, 환경 : 윈도우2003 MSSQL2000)
에서 테스트 해본 봐로는 처음페이지(1), 마지막 페이지(50000) 처리 시간이 아래와 같습니다.(단위 ms)

1 : 320    12289.06
2 : 273    11476.56
3 : 289    4406.25
4 : 289    2695.31
5 : 289    1218.75
6 : 7.81    23.44

엄청난 차이가 나죠??
기본적으로 글번호에 Clustered Index, 인덱스번호, 글깊이에 Non Clustered Index를 걸어 두었습니다.
엄청난 차이로 인해 테스트로 만든 저 또한 입이 쩍 벌어 집니다 ㅡㅡ;;

위 페이징 로직은 여기 저기서 줏어 듣고 ㅡㅡ; 확장 시킨 것입니다.

제가 내공 수위가 낮은 관계로 정확한 테스트를 행했는지 모르지만..
페이징으로 고생하시는 분들을 위해.. 간략하게 만들어 봤습니다.

기본 테스트는 제 홈페이지에서 해보시면 되구요.

테스트 asp파일은 [이곳] 에서 다운 받을수 있습니다.

제 홈에 있는 페이징 방법이 6번의 인덱스와 not in 으로 만들었습니다.
(그때는 걍.. 2000개 안쪽에서 처리 해주는 것이라 not in을 썻습니다 게시판이 필요 하시면..
  다운 받으셔서 저장 프로시저늬 리스트 부분을 수정 하시면. .더욱 쾨적하게 사용 하실수 있을것입니다)

p.s 궁금하신 점이나 문의 사항은 제 홈페이지의 테스트 게시판 버그 리포트에 적어 주시기 바랍니다.



테스트 페이지: http://neostory.net/Example/PagingTest/

출처 : http://www.knhead.pe.kr/PagingTest/
큰머리의 페이징 테스트 자료 이다.
지금은 없어졌지만 뉴스그룹에 올라왔길래 얼른 퍼다 놓는다.

Comment +0