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


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.