클러스터형 인덱스는 고유해야합니까?


84

클러스터형 인덱스가 고유하지 않으면 어떻게됩니까? 삽입 된 행이 일종의 "오버플로"페이지로 이동하기 때문에 성능이 저하 될 수 있습니까?

고유 한 "만들기"입니까? 그렇다면 어떻게해야합니까? 고유하게 만드는 가장 좋은 방법은 무엇입니까?

현재 클러스터형 인덱스를 사용하여 테이블을 논리적 부분으로 나누고 있기 때문에 질문하고 있지만 성능은 그저 그렇고 최근에는 클러스터형 인덱스를 고유하게 만드는 조언 을 받았습니다 . 그것에 대한 두 번째 의견이 필요합니다.

감사!

답변:


92

독특 할 필요 없지만 확실히 권장됩니다.
고유하지 않은 열에 CI를 생성하려는 시나리오는 아직 발생하지 않았습니다.

고유하지 않은 열에 CI생성 하면 어떻게 되나요?

클러스터형 인덱스가 고유 인덱스가 아닌 경우 SQL Server는 고유 자라는 내부 생성 값을 추가하여 중복 키를 고유하게 만듭니다.

이로 인해 성능이 저하됩니까?

고유자를 추가하면 계산 및 저장에 약간의 오버 헤드가 추가됩니다.
이 오버 헤드가 눈에 띄는 지 여부는 여러 요인에 따라 다릅니다.

  • 테이블에 포함 된 데이터의 양.
  • 삽입 비율은 얼마입니까?
  • 선택에서 CI가 사용되는 빈도입니다 (포함 인덱스가없는 경우 거의 항상).


Remus가 의견에서 지적한대로 편집 하면 고유하지 않은 CI를 만드는 것이 합리적인 선택이 될 수있는 사용 사례가 있습니다. 그러한 시나리오 중 하나를 만나지 않은 나는 단지 내 자신의 노출이나 능력이 부족하다는 것을 보여줄뿐입니다 (선택을 선택하십시오).


31
+1은 모든 것이 정확하지만 추가하고 싶을 때 발생합니다. 고유하지 않은 CI는 특정 (고유하지 않은) 열에 대한 범위 스캔이 일반적인 액세스 패턴 일 때 매우 일반적입니다.
Remus Rusanu

@Remus Rusanu : 나는 되었다 처럼 내 시나리오 문에 면책 조항을 추가하는 방법에 대해 생각 하지만 평균 아무것도하지 않습니다 . 유용 할 수있는 시나리오를 지적 해 주셔서 감사합니다.
리벤 Keersmaekers

4
@Remus : 'Departmentid'와 같은 고유하지 않은 열이있는 틈새 상황을 의미하며 'DepartmentId BETWEEN 1 and 100'과 같은 것을 쿼리합니까? 편집 아, 무슨 뜻인지 알겠습니다. 예 로깅 테이블의 날짜 열도 좋은 예입니다.
littlegreen 2010

안녕하세요, GUID 유형의 열인 동일한 "AggregateId"가있는 여러 행이있는 이벤트 스트림 테이블이 있습니다. 테이블에서 수행되는 유일한 쿼리는 주어진 AggregateId에 대한 모든 이벤트를 가져 오는 것입니다. 이것이 클러스터 된 인덱스 여야하는지 아니면 클러스터되지 않은 인덱스 여야하는지 궁금합니다.
Shayan C

@ShayanC-검색 성능이 기본 목표 인 경우 주어진 ID에 대한 모든 행을 검색 할 때 IO를 절약 할 수있는 CI로 만들 것입니다. 그러나 모든 성능 시나리오와 마찬가지로 확실한 유일한 방법은 측정하는 것입니다.
Lieven Keersmaekers

32

인덱싱의 여왕 Kimberly Tripp이이 주제에 대해 뭐라고 말했는지 확인하고 싶습니다.

몇 가지 이유로 클러스터링 키에 대한 권장 사항부터 시작하겠습니다. 첫째, 쉬운 결정이고 둘째,이 결정을 일찍 내리면 일부 유형의 조각화를 사전에 방지하는 데 도움이됩니다. 특정 유형의 기본 테이블 조각화를 방지 할 수있는 경우 일부 유지 관리 작업을 최소화 할 수 있습니다 (일부, SQL Server 2000 및 그보다 적은 경우 SQL Server 2005). 좋아, 나중에 재 구축에 대해 알아볼 게 .....

클러스터링 키에서 찾은 주요 사항부터 시작하겠습니다.

* Unique
* Narrow
* Static

왜 독특한가? 클러스터링 키 (있는 경우)가 모든 비 클러스터형 인덱스의 조회 키로 사용되기 때문에 클러스터링 키는 고유해야합니다. 예를 들어 책 뒷면의 색인을 살펴 보겠습니다. 색인 항목이 가리키는 데이터를 찾아야하는 경우 해당 항목 (색인 항목)은 고유해야합니다. 그렇지 않은 경우에는 어떤 색인 항목이 찾고 있는지 확인합니다. ? 따라서 클러스터형 인덱스를 만들 때 고유해야합니다. 그러나 SQL Server에서는 고유 한 열에 클러스터링 키를 만들 필요가 없습니다. 원하는 열에 만들 수 있습니다. 내부적으로 클러스터링 키가 고유하지 않은 경우 SQL Server는 데이터에 4 바이트 정수를 추가하여이를 "고유 화"합니다. 따라서 클러스터형 인덱스가 고유하지 않은 항목에 생성되면 인덱스 생성시 추가 오버 헤드가있을뿐만 아니라 낭비되는 디스크 공간이 있습니다.

출처 : 계속 증가하는 클러스터링 핵심 논쟁-다시!


그러나 질문은 Queen이 데이터를 단일화하기 위해 newsequentialid를 권장하지만 SQL Server는이를 지정하지 않으면 고유 한 고유 식을 생성합니다. 그렇다면 자신의 순차 ID를 추가해야 할 이유가 있습니까?
littlegreen 2010

2
@littlegreen : 그녀는 GUID (클러스터링 인덱스에서 사용하기에 정말 좋지 않음)를 사용한다고 주장한다면 최소한 newsequentialid()거의 순차적 인 GUID를 얻기 위해 사용한다고 말합니다 . 하지만 예 : 고유 한 ID 추가 하면 (항상 INT IDENTITY를 선호합니다) 해당 값을 가지고 있고이를 사용할 수 있습니다 (예 : FK 관계 설정). SQL Server에 추가 된 고유 요소는 사용자에게 표시되지 않으므로 사용할 수없는 오버 헤드 일뿐입니다.
marc_s

내가 참조. 처음 두 개 대신 (CompanyID, DepartmentID, id INT IDENTITY) 클러스터형 인덱스를 선호하는 인수입니다. 감사!
littlegreen

1
@littlegreen : 더 나은 방법- (ID INT IDENTITY) 에서만 클러스터형 인덱스를 만들고 필요한 경우 다른 필드를 클러스터되지 않은 별도의 인덱스에 넣습니다. 클러스터형 인덱스는 가능한 한 작아야합니다. 결국 클러스터형 인덱스 열이 해당 테이블에있는 각각의 모든 비 클러스터형 인덱스의 모든 항목에 추가되므로 넓은 클러스터형으로 바이트를 낭비하지 마십시오. 인덱스!
marc_s

1
예,하지만 모든 부서 데이터가 그룹화되는 이점을 잃고 전체 부서를 한 번에 삽입 / 삭제 / 검색 할 수 있습니다. 내 데이터가 흩어져 부서 전체 또는 회사 전체에 대한 삽입 / 삭제 속도가 느려집니다. 내 쿼리는 한 번에 한 회사에서만 실행되며 전체 데이터 세트를 자주 업데이트해야합니다.
littlegreen 2010

9

클러스터형 인덱스는 고유해야합니까?

그렇지 않으며 그렇지 않은 경우 더 나은 때가 있습니다.

반 무작위, 고유 EmployeeId 및 각 직원에 대한 DepartmentId가있는 테이블을 고려하십시오. select 문이 다음과 같은 경우

SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%

그러면 DepartmentId고유 인덱스가 아니더라도 (또는 특히) 클러스터형 인덱스 인 경우 성능에 가장 좋습니다 (주어진 DepartmentId 내의 모든 레코드가 클러스터링되도록하기 때문에 성능에 가장 적합합니다).


참고 문헌이 있습니까?

거기에 클러스터 된 인덱스 디자인 지침 말한다 예는,

몇 가지 예외를 제외하고 모든 테이블에는 다음을 제공하는 열 또는 열에 정의 된 클러스터형 인덱스가 있어야합니다.

  • 자주 사용하는 쿼리에 사용할 수 있습니다.
  • 높은 수준의 고유성을 제공합니다.
  • 범위 쿼리에 사용할 수 있습니다.

예를 들어 "높은 수준의 고유성"에 대한 나의 이해는 대부분의 쿼리가 주어진 도시 내의 레코드를 선택하려는 경우 클러스터 된 인덱스로 "국가"를 선택하는 것이 좋지 않다는 것입니다.


네, 지금까지 그렇게 생각했지만 정반대의 충고도 들어서 어느 것이 사실인지 궁금합니다. 참고 문헌이 있습니까?
littlegreen 2010

@littlegreen 귀하의 질문에 답하기 위해 내 대답을 편집했습니다.
ChrisW

감사. 네, 당신의 요점을 알겠습니다. 그러나 정기적으로 한 번에 전체 국가를 삽입하는 경우 (국가, 마을)에 대한 클러스터형 인덱스는 데이터 정렬이 필요하기 때문에 나에게 번거로울 것입니다. 다른 한편으로, 삽입 전 종류는 그다지 문제가되지 않을 것입니다 ...
littlegreen

3
확실히 귀하의 예에서 {DepartmentID, EmployeeID}의 고유 클러스터형 인덱스가 더 좋을까요? 기존 필드가 더 적은 오버 헤드 (아마도 4 바이트 INT)로 고유성을 제공하고 인덱스 내에서만 몇 가지 쿼리를 더 실행할 수 있는데 시스템이 고유자를 만드는 이유는 무엇입니까?
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.