728x90

김정선의 좋은 글을 찾아서……
SQL Server 인덱스 구성 전략(시리즈-3. 정렬된 파티션 인덱스)

 

 

사용자 삽입 이미지
김정선(jskim@feelanet.com)

필라넷 DB사업부 수석컨설턴트

SQLServer 아카데미/트라이콤 교육센터 강사

 

Microsoft SQL Server MVP

MCT/MCITP/MCDBA



Part 3: 오프라인, 직렬/병렬 파티셔닝(정렬된 파티션 인덱스 구성)

파티션 인덱스 구성에는 2가지 주요 범주가 있다:

-       정렬된(Aligned): 해당 개체(테이블)과 인덱스가 동일 파티션 스킴(scheme)을 사용하는 경우
(
역주: 본문에 schema로 적고 있다, 오타일까? 의도적인 것일까? ^^)

-       정렬되지 않은(Non-Aligned): 힙과 인덱스가 서로 다른 파티션 스킴을 사용한 경우

 

정렬된 파티션에 직렬 인덱스 구성

 

NL

                /       \

             CTS   Builder (write data to the in-build index)

                           \

                        [Sort] (order by index key) <-- optional

                             \

                          Scan (read data from source)

 

CTS: Constant Table Scan(이는 인덱스 구성자(builder)에게 파티션 ID를 제공하는 역할)

NL: Nested Loop

 

정렬된 파티션 인덱스를 구성하는 경우엔Constant Table Scan이 각각의 파티션 ID를 제공하고 이를 이용해 한 번에 하나의 파티션을 대상으로 인덱스 구성을 작업을 수행하며 Nested Loop 통해 이러한 작업을 반복 수행하게 된다. 각 정렬 테이블은 한 번에 하나씩 생성되어 처리되고 최종 b-tree 구성도 각 파티션 별로 하나씩 구성하므로 모든 파티션에 대해 정렬 테이블을 유지할 필요가 없다. 결국 한 번에 하나의 정렬 테이블만 있으면 된다.

 

이것이 필요한 디스크 공간에 미치는 영향은:

-       사용자 데이터베이스에서 정렬하는 경우(기본값) 각 파티션 별 해당 파일 그룹에서 정렬한다. 각 파일 그룹별로 2.2 x (파티션 크기) 만큼이 필요한 것이다. 예를 들어, 파일 그룹 FG1, FG2, FG3 3개의 파티션을 가지며 각 인덱스는 1GB, 2GB, 3GB를 소비한다면. 이 경우 FG1 2.2 x 1 = 2.2GB, FG2 2.2 x 2 = 4.4GB 그리고 FG3 2.2 x 3 = 6.6GB의 공간을 요구하는 것이다.

-       SORT_IN_TEMPDB = ON 인덱스옵션을 사용해서, tempdb를 정렬 공간으로 사용하는 경우 정렬 테이블에 대해 tempdb의 동일 공간을 재사용할 수 있게 된다. 한 번에 하나씩 파티션을 정렬하므로 실제론 2.2 x (가장 큰 파티션의 크기)만큼만 필요하게 되는 것이다.

(역주: 원문에는 위 사이즈에 대한 전체 크기 결과를 언급하고 있지만, 역자의 판단으로 설명과 결과가 맞지 않아 해당 부분의 설명은 생략했습니다)

 

메모리 고려 사항

한 번에 하나의 정렬 테이블만을 가진다면, 필요 메모리 크기는 최소 40페이지이다. 따라서 전체 메모리 계산식은

전체 메모리 = 최소 필요 메모리 + 추가 메모리*

 

*추가 메모리는 행 크기 x 예상 행 수로 계산되며 쿼리 최적화 프로그램에 의해서 제공된다.

 

 

 

정렬된 파티션에 병렬 인덱스 구성

파티션 인덱스에 대한 병렬 구성은 스캔과 정렬이 병렬로 수행되며 동시 실제 동시 작업자 수에 따라 실제 동시에 필요한 정렬 테이블수가 결정된다. 파티션은 작업자에 의해서 하나씩 선택되며 한 작업자가 작업을 완료하며 미 처리된 또 다른 파티션을 가지고 처리한다. 각 작업은 0 ~ N 파티션(한 파티션을 여러 작업자 공유하지는 않는다)을 구성한다. 0이 포함된 이유는 DOP > 파티션 수의 경우, 모든 작업자에게 파티션이 하나씩 돌아가지 않을 수도 있기 때문이다. 먼저 온 놈이 임자다 ^^

 

한 파티션을 여러 작업자가 공유하지 않으므로, 가장 큰 파티션에 병목이 발생할 수 있다. 다른 작업자는 모두 작업을 완료했지만 가장 정렬 작업자는 여전히 수행하고 있는 것이다. 더불어 해당 리소스(메모리 스레드 등)는 다른 쿼리에 의해서 재사용하지도 못한다.

 

마지막 단계의 짜집기도 필요 없다. 어차피 각 파티션이 분리된 b-tree에 해당하므로.

 

이것이 필요한 디스크 공간에 미치는 영향은:

-       사용자 데이터베이스에서 정렬하는 경우 각 파일 그룹별 2.2 x (파티션 크기)만큼을 요구한다.

-       tempdb를 사용한 경우 앞서의 직렬 처리에서의 이득을 동일하게 가질 수 없다. 병렬 처리이므로 동시에 여러 정렬 테이블을 처리해야 한다. 파티션 간의 데이터 실제 분포 정보를 모르는 한 2.2 x (인덱스 전체 크기)만큼의 여유 공간을 필요로 한다.

 

메모리 고려 사항

위에서 설명한 내용에 따라, 필요 메모리는 DOP수에 의존한다. ,

 

전체 메모리 = 40 x DOP + 추가 메모리

 

추가 메모리를 직렬/병렬 계획과는 무관하다.

 

 

다음 마지막 주제는,

시리즈-4. 정렬되지 않은 파티션 인덱스 구성

입니다. 또 기다려 주세요~~~

728x90
Select T1.*,
T2.BudgetCD, (T2.OutGubun + ' ' + T2.BudgetName) AS BudgetName
From SBN06 T1, dbo.fn_GET_BudgetCD( @pInstitutionCD , '3' ) T2
Where InstitutionCD = @pInstitutionCD
And T1.BasisDT Between @pSDate And @pEDate
And T1.BudgetCDID = T2.BudgetCDID
Order By
CASE WHEN @pGubun = 'DAY' THEN T1.BasisDT END ,
CASE WHEN @pGubun = 'CODE' THEN T2.BudgetCD END
, T1.ExpenditureNum, T2.BudgetCD 
728x90
올바른 순위 정렬 결과를 얻으려면 (1) : 올바른 순위 정렬 결과를 얻으려면


ORDER BY를 실행하여 정렬하면 순위를 간단히 출력할 수 있지만 아쉽게도 같은 값이 존재한다면 같은 순위를 부여해야 한다.
예를 들어 아래와 같은 순위 결과를 출력하고 싶다면 어떤 쿼리를 활용해야 할까?

성적 테이블

순위 이름 점수
1 김진수 99
2 김영은 87
2 김한영 87
4 정진은 65

위의 표에서 나타나듯 김영은씨와 김한영씨는 같은 점수이다. 결국 공동2위로 순위표가 정상으로 출력되었다.
위와 같은 결과를 출력시키기 위해서는 그 사람의 점수보다 성적이 좋은 사람이 몇 명 있는지를 계산해야 한다.
서브쿼리를 활용하여 기술하면 위와 같은 올바른 순위 정렬 결과를 얻을 수 있다.

SELECT ( SELECT COUNT (*) + 1 FROM 성적 WHERE 성적.점수 > S.점수),S.이름, S.점수 FROM 성적 S



먼저 서브 쿼리를 통해 순위값을 구한다. 자신보다 성적이 좋은 사람이 없으면 COUNT(*)의 값은 0이되고
결국 +1을 통해 순위에 1이 리턴된다.

제공 : 코리아인터넷닷컴, a 2001년 11월 19일 

+ Recent posts