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

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

 

 

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

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

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

 

Microsoft SQL Server MVP

MCT/MCITP/MCDBA

 


Part 4: 오프라인, 직렬/병렬 파티셔닝(정렬되지 않은 파티션 인덱스 구성)

정렬되지 않은 경우는 힙과 인덱스가 서로 다른 파티션 스킴을 사용하거나, 힙이 파티션되지 않은 경우이다.

이번 글에서 원본 데이터가 파티션 된 경우와 그렇지 않은 2가지 경우의 정렬되지 않은 파티션 인덱스 구성에 대해 다룰 것이다.

 

원본이 파티션 되지 않은 경우

다음 쿼리를 보자.

 

Create Partition Function pf (int) as range right for values (1, 100, 1000)

Create Partition Scheme ps as Partition pf
ALL TO ([PRIMARY])

Create table t (c1 int, c2 int) 테이블은 디폴트로 PRIMARY 파일 그룹에 생성

Create clustered Index idx_t on t(c1) on ps(c1)  -정렬되지 않은 인덱스 구성

 

직렬 계획은 간단하다,

 Index Insert (write data to the in-build index)
   |
 Sort (order by index key)
   |
 Scan (read data from source)

 

Sort 반복연산자(iterator)는 각 파티션당 하나의 정렬 테이블을 만든다(예제에서는 4개의 파티션이 존재하므로 동시의 4개의 정렬 테이블이 만들 것이다). 디폴트로, 데이터 정렬을 위해 사용자 데이터베이스를 사용한다. 이전에 언급한대로, 정렬 데이터에서 모든 데이터를 복사하고 나면 각각의 익스텐트를 해제한다. 이 동작을 통해서 각 파티션 별로 필요한 디스크 공간을 3 x 파티션크기에서 2.2 x 파티션 크기로 줄일 수 있다. 따라서 각 파일 그룹은 2.2 x (해당 파일 그룹에 속한 전체 파티션 크기)만큼의 디스크 공간을 요구한다. SORT_IN_TEMPDB 옵션을 지정한다면, 모든 정렬 테이블은 tempdb에서 다루어질 것이고, 2.2 x (인덱스 전체 크기)만큼의 여유 공간을 tempdb에 요구할 것이다.

 

Index Insert 반복연산자는 sort 반복연산자가 정렬을 완료하고 나면 인덱스 구성을 시작한다. 파티션 수 만큼의 정렬 테이블이 필요하므로, 각 정렬 테이블 당 최소 40페이지가 필요함을 상기한다면, 최소 필요 메모리는 파티션 수 x 40페이지가 될 것이다.

 

병렬 계획이 된다면,

 

X (Exchange)
   |
 Index Insert
   |
 Sort
   |
 Scan

 

각 작업자 스레드가 병렬 처리 수와 해당 파티션 수만큼 계산되어 할당된다 (예를 들어, 4개의 파티션에 4개의 작업자 스레드이면 각 스레드 당 1개의 파티션). Sort 반복연산자를 할당된 각 파티션에 대해 하나의 정렬 테이블을 생성한다. 각 작업자는 원본 데이터를 한 번 스캔하고 그 파티션에 속한 행들을 처리한다, 처리된 행들은 소속된 파티션에 따라 해당 정렬 테이블에 입력된다.

 

모든 정렬 테이블이 완성되면, 인덱스 구성자가 정렬 테이블을 하나씩 처리하며, 각 파티션의 파일 그룹별로 b-tree를 구성하게 된다.

디스크 공간 및 메모리 필요 사항은 이전의 직렬 계획과 동일하다. 두 경우 모드, 모든 정렬 테이블이 완성되기 전까지 인덱스 구성을 시작할 수 없기 때문이다.

 

 

 

원본이 파티션된 경우

원본 테이블이 이미 파티션된 경우엔, 파티션 인덱스를 구성할 때 그 방법을 바꿀 수 있다.

예를 들어, 원본 테이블과 동일한 파티션 함수와 스킴을 사용하되, 새로운 인덱스는 다른 칼럼으로 파티션될 수 있다.

CREATE TABLE t (c1 int, c2 int) ON ps (c2)

……

CREATE CLUSTERED INDEX idx_t ON t(c1) ON ps(c1)

 

직렬 계획은 다음과 같다,

    Index Insert
       |
     Sort
       |
      NL (Nested Loop)
     /    \
 CTS   Scan


Constant Table Scan 연산자에 의해 파티션 ID를 하나씩 넘겨주면, NL 연산자에 의해서 해당 파티션 데이터를 스캔하고 결과를 Sort 반복연산자에 넘겨준다. 여기서부터 원본이 정렬되지 않은 시나리오와 동일하다. 메모리와 디스크 요구 사항 또한 같다.

 

병렬 계획의 경우는,

 

X (Distribute Streams)
       |
     Index Insert
       |
     Sort
       |
       X (Repartition Streams)
       |
      NL
     /   \
   X    Scan
  /
CTS

 

CTS위에 있는 연산자가 Gather Streams 연산자이다, 그 말은 생성자 하나의 다중 소비자를 가진다는 뜻이다 (역주: Gather Stream연산자에 다중 입력 처리를 통해 병렬 처리를 수행하고 이를 단일 출력으로 제공하는 연산자이다). Gather Streams Repartition Streams 연산자 사이에, 원본 파티션 수에 병렬 처리 수를 나눈 만큼의 작업자가 할당된다. 원본은 한 번만 스캔한다.

Repartition Streams 연산자는 쿼리 계획을 두 개의 병렬 처리 영역으로 분리한다. 최상위에 있는 Distribute Streams 연산자와 Repartition Streams 연산자 사이에서는 앞서 Repartition Streams 아래에서 만들어진 작업자 집합과는 또 다른 집합을 가진다. 각 작업자가 대상 파티션에 할당되는데 그 수는 대상 인덱스 파티션 수를 병렬 처리 수로 나눈 만큼 할당된다. 나머지 정렬 및 인덱스 구성 작업은 이전의 원본이 파티션되지 않은 경우의 병렬 처리와 동일하며, 메모리 및 디스크 공간 또한 동일하다.

 

 

여기까지입니다.

계속 살펴봐 주신 분들에게 감사드립니다.

더불어 원본에서 다음 문서가 또 올라오면 이어서 계속 소개해 드리도록 하겠습니다.


그럼, 일단 이 시리즈 문서는 접구요,

다음에 또 다른 재미있는 자료를 번역해서 공유하도록 하겠습니다.


행복한 하루 되세요~~~

728x90

사용된 명령어 정리

저장 프로시저
저장 프로시저 이름 설명
sp_readerrorlog SQL Server 오류 로그를 반환합니다.
sp_cycle_errorlog SQL Server를 재시작하지 않고 새로운 오류 로그 파일만 생성합니다.
sp_helpserver master.dbo.sysservers 시스템 테이블에 등록된 정보를 반환합니다.
sp_dropserver master.dbo.sysservers 시스템 테이블에서 서버를 삭제합니다.
sp_addrserver master.dbo.sysservers 시스템 테이블에 서버를 등록합니다.
sp_serveroption master.dbo.sysservers 시스템 테이블에서 등록된 서버의 옵션을 변경합니다.
sp_blocker_pss80 잠금 정보와 블로킹하는 프로세스와 블로킹 당하는 프로세스의 정보를 반환합니다.
http://support.microsoft.com/default.aspx?scid=kb;en-us;299518
sp_tempdbspapce tempdb 의 공간 사용 정보를 반환합니다.
sp_configure 서버의 구성 옵션을 변경합니다.
sp_attach_db 데이터베이스를 SQL Server에 연결합니다.
sp_attach_single_file_db 로그 파일이 손실된 데이터베이스를 SQL Server에 연결합니다.
sp_detach_db 데이터베이스를 분리합니다.
sp_resetstatus 데이터베이스에서 주의 대상 플래그를 해제합니다.
sp_helpfile 현재 데이터베이스 파일의 물리적 이름 및 특성을 반환합니다.
sp_change_users_login 로그인 계정과 사용자 계정의 연결을 설정합니다.
sp_hexadecimal Binary값이나 Decimal값을 16진수 형태의 varchar 타입으로 변경한 값을 반환합니다.
http://support.microsoft.com/KB/246133
sp_help_revlogin 원본과 동일한 SID와 패스워드를 가지는 로그인을 생성하는 스크립트를 반환합니다.
http://support.microsoft.com/KB/246133
 
DBCC 명령어
DBCC 명령 설명
DBCC ERRORLOG 새로운 SQL Server 오류 로그를 생성합니다.
DBCC SHOW_STATISTICS 인덱스의 통계 정보를 보여 줍니다.
온라인 설명서 참조.
DBCC SHOWCONTIG 인덱스의 단편화 정보를 보여 줍니다.
온라인 설명서 참조
DBCC DBREINDEX 인덱스를 재구성합니다.
온라인 설명서 참조
DBCC INDEXDEFRAG 인덱스의 페이지를 재정렬합니다.
온라인 설명서 참조
DBCC SQLPERF
(WAITSTATS)
각 대기 유형별로 대기 시간을 확인합니다.
DBCC SQLPERF
(LOGSPACE)
로그 파일의 사용 공간을 확인합니다.
온라인 설명서 참조
DBCC INPUTBUFFER 해당 프로세스의 명령문을 확인합니다.
온라인 설명서 참조
DBCC CHECKDB 지정한 데이터베이스에서 모든 개체의 할당과 구조적 무결성을 검사합니다.
온라인 설명서 참조
DBCC CHECKTABLE 지정한 테이블에서 할당과 구조적 무결성을 검사합니다.
온라인 설명서 참조
DBCC DBRECOVER 데이터베이스를 재시작하지 않고 복원합니다.
DBCC REBUILD_LOG 로그 파일 손상 시에 새로운 로그 파일을 생성합니다.
DBCC TRACE 추적 플래그를 설정합니다.
온라인 설명서 참조
DBCC TRACESTATUS 추적 플래그 설정 여부를 보여 줍니다.
온라인 설명서 참조


자세한 설명은 온라인 설명서와 SQL Server DBA 가이드를 참조하기 바랍니다.
 
유틸리티
유틸리티 이름 설명
Portqry.exe 윈도우즈 서버에서 사용중인 포트 상태를 점검합니다.
http://support.microsoft.com/kb/310099
Componet Checker
(cc_pkg.exe)
MDAC 버전 정보 및 파일 정보를 점검합니다.
http://msdn.microsoft.com/data/mdac/downloads/default.aspx
SQLDiag.exe SQL Server 진단 툴입니다.
C:\Program Files\Microsoft SQL Server\MSSQL\Binn
Ostress.exe 커넥션 및 스트레스 테스트를 합니다.
http://www.microsoft.com/downloads/details.aspx?FamilyId
=5691AB53-893A-4AAF-B4A6-9A8BB9669A8B&displaylang=en
Rebuildm.exe 시스템 데이터베이스를 재구성합니다.
C:\Program Files\Microsoft SQL Server\MSSQL\Binn
DTCPing.exe MSDTC 의 구성 정보와 상태 정보를 점검합니다.
http://support.microsoft.com/default.aspx?scid=kb;ko;306843
 
시작옵션 및 추적 플래그
시작 옵션 및 매개 변수 설명
/d master 데이터베이스 데이터 파일의 위치를 지정합니다.
/l master 데이터베이스 로그 파일의 위치를 지정합니다.
/e SQL Server 오류 로그 파일의 위치를 지정합니다.
/f 최소 구성으로 시작합니다.
/m 단일 사용자 모드로 시작합니다.
/c SQL Server를 서비스로 시작하지 않고 응용 프로그램으로 시작합니다.
/g 확장 저장 프로시저, OLE 자동화 개체, 분산 쿼리 등을 위한 메모리 공간을 MB단위로 지정합니다.
/x CPU 시간과 캐시 적중률 통계를 유지할 수 없도록 합니다. 해당 정보를 모니터링할 필요가 없는 경우에 지정하면 성능이 다소 향상됩니다.
-T 추적 플래그를 설정합니다.
T1118 모든 데이터베이스에 유니폼 익스텐트만 할당합니다.
(7.0 에서는 인덱스 생성 시 등에 오류가 발생합니다.)
T1204 교착 상태를 모니터링하여 SQL Server 오류 로그에 기록합니다.
T1807 UCN 경로를 이용하여 네트워크 드라이브에 데이터 파일 및 로그 파일을 생성할 수 있습니다.
T2520 DBCC PAGE 등 문서화 되지 않은 DBCC 명령어의 매개 변수를 DBCC HELP를 통해서 확인 합니다.
T3604 DBCC 실행 결과를 화면에 출력합니다.
T3605 DBCC 실행 결과를 SQL Server 오류 로그에 기록합니다.
T3607 모든 데이터베이스에서 인스턴스 복구 프로세스를 생략합니다.
T3608 master 데이터베이스를 제외한 모든 데이터베이스에서 인스턴스 복구 프로세스의 실행을 생략합니다.
T3609 tempdb 생성을 생략합니다.
T4013 새로운 연결이 생성되는 경우 해당 정보를 SQL Server 오류 로그에 기록합니다.
T4220 Startup procedure의 실행을 비활성화합니다.
T7300 OLEDB의 보다 상세한 오류 메시지를 반환 받을 수 있습니다.
T8602 인덱스 힌트를 적용하지 않습니다.
T8755 잠금 힌트를 적용하지 않습니다.

마치면서

"이 세상에 진리는 존재하지 않는다, 객관성을 가장한 주관적 해석만이 존재할 뿐이다"라는 말이 있습니다. 지금은 최선의 방법이라고 생각할지 모르지만 하룻밤이 지나고 나면 더 적절한 방법을 발견하거나 추가적인 조치가 미비했음을 인지할 때가 있습니다. 점차 엔진이 발달하고 핫픽스가 개발되어짐에 따라서 어제의 방법이 더 이상 최선의 선택이 아닐 수도 있다는 사실을 유념하시기 바랍니다. 이 조그마한 지식을 바탕으로 끊임없이 발전하는 여러분을 기대합니다.

+ Recent posts