2008-11-10 3 views
29

일반적으로 GUID를 기본 키로 사용하는 데이터베이스에서 작업하고 있습니다.GUID 열에서 클러스터형 인덱스를 제거해야합니까?

기본적으로 SQL Server는 클러스터 된 인덱스를 기본 키 열에 배치합니다. 이 GUID 열에 대한 어리석은 아이디어이며 클러스터되지 않은 인덱스가 더 나은 이해합니다.

클러스터 된 모든 인덱스를 제거하고 클러스터되지 않은 인덱스로 대체해야한다고 생각합니까?

SQL의 성능 튜너가 권장하지 않는 이유는 무엇입니까?

+0

Paul Randal의 다음 게시물을 살펴보십시오. [임의의 GUID에 대한 클러스터 된 인덱스 또는 클러스터되지 않은 인덱스?] (http://www.sqlskills.com/blogs/paul/clustered-or-nonclustered-index-on-a-random-guid/) – Lijo

답변

25

클러스터 된 인덱스의 큰 이유는 주어진 열의 값 범위에 대한 행을 검색하려는 경우가 많기 때문입니다. 데이터가 순서대로 물리적으로 배열되기 때문에 행을 매우 효율적으로 추출 할 수 있습니다.

GUID와 같은 것이 기본 키로는 뛰어나지 만 삽입에 추가 비용이 들고 선택에 지각 할 수있는 이점이 없기 때문에 성능에 긍정적 인 영향을 줄 수 있습니다.

그래, GUID에 인덱스를 클러스터링하지 마십시오.

권장 사항으로 제공되지 않는 이유는 튜너가이 사실을 알고 있다는 것입니다.

+2

SQL 2005 및 newsequentialid()를 사용하면 조각화 문제가 크게 사라집니다. sys.dm_db_index_physical_stats 및 sys_indexes를보고 측정하는 것이 가장 좋습니다. – RoadWarrior

+0

그래도 여전히 쿼리에 도움이되지는 않습니다. 필요한 경우 UNIQUEIDENTIFIER에만 클러스터해야합니다. 복제를 위해. –

4

GUID 필드의 클러스터 된 인덱스 문제는 GUID가 무작위이므로 새 레코드가 삽입 될 때 디스크의 중요한 부분을 이동시켜 테이블 중간에 레코드를 삽입해야합니다 .

그러나 정수 기반 클러스터 된 인덱스의 경우 정수는 일반적으로 IDENTITY 사양과 같이 순차적이므로 정수를 기반으로 데이터를 이동하지 않아도됩니다.

반면 클러스터 된 인덱스는 GUID에 항상 나쁜 것은 아닙니다 ... 모두 응용 프로그램의 필요에 따라 다릅니다. SELECT 레코드를 신속하게 사용할 수 있어야하는 경우 클러스터 된 인덱스를 사용하십시오 ... INSERT 속도가 저하되지만 SELECT 속도가 향상됩니다.

0

예 Galwegian이 위의 이유로 GUID 기본 키의 클러스터 된 인덱스를 제거해야합니다. 우리는 우리의 응용 프로그램에서이 작업을 수행했습니다.

0

많은 삽입 작업을 수행 중이거나 PK로 매우 빠른 조회가 필요한 경우에 따라 다릅니다.

+0

클러스터링은 조회에 영향을 미치지 않습니다. 속도 - 고유 한 클러스터되지 않은 인덱스가 작업을 수행해야합니다. –

4

NewId()를 사용하는 경우 NewSequentialId()로 전환 할 수 있습니다. 그것은 인서트 퍼포먼스를 도와야합니다.

5

GUID를 클러스터링하는 것은 일반적으로 좋지 않지만 GUID는 경우에 따라 cause fragmentation even in non-clustered indexes 일 수 있습니다.

SQL Server 2005를 사용하는 경우 newsequentialid() 함수는 순차 GUID를 생성합니다. 이렇게하면 조각화 문제를 방지하는 데 도움이됩니다.

내가 같은 SQL 쿼리를 사용 제언 (비 ANSI 구문을 용서) 어떤 결정을하기 전에 조각을 측정하기 위해 다음

SELECT OBJECT_NAME (ips.[object_id]) AS 'Object Name', 
     si.name AS 'Index Name', 
     ROUND (ips.avg_fragmentation_in_percent, 2) AS 'Fragmentation', 
     ips.page_count AS 'Pages', 
     ROUND (ips.avg_page_space_used_in_percent, 2) AS 'Page Density' 
FROM sys.dm_db_index_physical_stats 
    (DB_ID ('MyDatabase'), NULL, NULL, NULL, 'DETAILED') ips 
CROSS APPLY sys.indexes si 
WHERE si.object_id = ips.object_id 
AND si.index_id = ips.index_id 
AND ips.index_level = 0; 
2

예, 아무 소용이 없다 임의의 값에 클러스터 된 인덱스를 필요에 .

아마도 데이터베이스에 클러스터 된 인덱스가 필요합니다. 예를 들어, "Author"테이블과 "Author"에 대한 외래 키가있는 "Book"테이블이 있고 응용 프로그램에 "Select ... from Book where AuthorId = .."라는 쿼리가있는 경우 "라고 말하면, 당신은 일련의 책을 읽을 것입니다. 디스크 헤드가 해당 저자의 모든 서적을 모으는 섹터에서 섹터로 바운스 할 필요가 없도록 해당 책이 디스크에서 서로 물리적으로 인접 해 있으면 더 빠를 것입니다.

따라서 응용 프로그램과 데이터베이스를 쿼리하는 방법에 대해 생각해 봐야합니다.

변경하십시오. 당신이 알고하지 않기 때문에

그리고 시험, ...

24

당신은 거의 확실 데이터베이스의 모든 테이블에 클러스터 된 인덱스를 설정합니다. 테이블에 클러스터 된 인덱스가없는 경우이를 "힙"이라고하며 대부분의 일반 쿼리 유형의 성능은 less for a heap than for a clustered index table입니다.

클러스터 된 인덱스를 설정해야하는 필드는 테이블 자체와 테이블에 대해 예상되는 쿼리 사용 패턴에 따라 다릅니다. 거의 모든 경우에 클러스터형 인덱스가 고유 한 열 또는 열의 조합 (예 : 대체 키)에 있어야합니다. SQL이 아닌 경우 SQL은 고유 한 값을 끝에 추가합니다. 필드를 선택하십시오. 테이블에 여러 레코드를 선택하거나 필터링하기 위해 쿼리에서 자주 사용되는 열이있는 경우 (예 : 테이블에 판매 트랜잭션이 포함되어 있고 응용 프로그램이 제품 ID별로 판매 트랜잭션을 자주 요청하거나 더 나은 경우) 거의 모든 경우 특정 송장에 대한 모든 세부 레코드를 검색 할 인보이스 세부 정보 테이블 또는 특정 고객에 대한 모든 송장을 자주 가져 오는 송장 테이블 ... 여기서 선택하는 것은 큰지 단일 값으로 레코드 수 또는 값 범위로)

이 열은 클러스터 된 인덱스의 후보입니다. 클러스터 된 인덱스의 열 순서는 매우 중요합니다. 인덱스에 정의 된 첫 번째 열은 예상 쿼리에서 처음에 선택되거나 필터링되는 열이어야합니다.

이 모든 이유는 데이터베이스 인덱스의 내부 구조를 이해했기 때문입니다. 이러한 인덱스를 균형 트리 (B-Tree) 인덱스라고합니다. 트리의 각 노드는 두 개가 아닌 임의의 수의 항목 (및 하위 노드)을 가질 수 있다는 점을 제외하면 이진 트리와 매우 유사합니다. 클러스터 된 인덱스를 다른 것으로 만드는 것은 클러스터 된 인덱스의 리프 노드가 테이블 자체의 실제 실제 디스크 데이터 페이지라는 것입니다. 비 클러스터형 인덱스의 리프 노드는 테이블의 데이터 페이지를 "가리 킵니다".

테이블에 clsutered 인덱스가있는 경우 테이블 데이터 페이지는 해당 인덱스의 리프 수준이며 각 인덱스는 이전 페이지와 인덱스 순서의 다음 페이지에 대한 포인터를 갖습니다 연결된 목록).

쿼리가 clustered 인덱스와 동일한 순서의 행 범위를 요청하면 ... 프로세서는 인덱스를 한 번만 (또는 두 번) 탐색하고 데이터의 시작 페이지를 찾고, 필요한 모든 데이터 페이지를 읽을 때까지 링크 된 목록 포인터를 따라 다음 페이지와 다음 페이지로 이동하십시오.

클러스터되지 않은 인덱스의 경우 검색하는 모든 행에 대해 한 번 인덱스를 탐색해야합니다.

참고 : EDIT
Guid 키 열의 순차적 문제를 해결하려면 SQL2k5에 GUID를 "이전"순차 방식으로 생성하는 NEWSEQUENTIALID()가 있음을 알아 두십시오.

또는 지미 Nielsens COMB에게 클라이언트 측 코드에서 구현되는 GUID algotithm 조사 할 수 있습니다 :

COMB Guids

+3

그러나 GUID는 무엇입니까? 순차 GUID가 아닌 한 클러스터형 인덱스와 동일한 순서로 행 범위를 검색하지 않습니다. 따라서 내 질문 – cbp

+0

일반적으로 non-clustered 인덱스는 인덱스가 아닌 열을 가져와야 할 때 단일 행 액세스의 클러스터 된 인덱스보다 약간 빠릅니다. 색인을 "덮어두기"위해, 그것은 중요하지 않습니다. (con't) –

+2

그러나 비 순차적 Guid를 사용하는 경우에도 클러스터 된 인덱스는 데이터의 "그룹"쿼리에 도움이 될 수 있습니다. GUID가 상위 테이블 (예 : PK) 및 하위 테이블의 복합 클러스터 인덱스 (PK) 인덱스의 첫 번째 (FK) 열인 경우 모든 클러스터 된 인덱스 혜택이 적용됩니다. –

0

대부분이 언급 한 것처럼를 클러스터 된 인덱스에서 임의의 식별자를 사용하지 마십시오. 클러스터링의 이점을 얻을 수 없습니다. 사실, 지연이 증가합니다. 그들 모두를 제거하는 것은 충실한 조언입니다. 또한 newsequentialid()는 다중 마스터 복제 시나리오에서 매우 문제가 될 수 있습니다. 데이터베이스 A와 B가 모두 복제 전에 newsequentialid()를 호출하면 충돌이 발생합니다.

관련 문제