인덱싱 된 뷰가 고유하지 않은 클러스터형 인덱스를 허용하지 않는 이유는 무엇입니까?


12

인덱싱 된 뷰를 사용하여 가장 일반적으로 사용되는 몇 가지 뷰의 성능을 향상시키는 방법을 찾고 있습니다.

그러나 인덱싱 된 뷰는 고유하지 않은 클러스터형 인덱스를 지원하지 않으므로 나머지 데이터베이스 구조에서 설정 한 우선 순위와는 약간 다릅니다.

예를 들어, 다음은 몇 가지 테이블의 단순화 된 버전입니다.

-Groups-
Group ID    GroupName

-Users-
UserKey    UserName    FullName     GroupID

인덱스는 Groups.GroupID (비 클러스터형) 및 Users.GroupID (클러스터형)에 있습니다. 가장 일반적으로 특정 그룹의 사용자 범위가 검색 될 때 Users 테이블의 GroupID에있는 클러스터 키. 분명히 그룹당 여러 명의 사용자가 있으므로이 클러스터형 인덱스는 고유하지 않습니다.

고유하지 않은 클러스터형 인덱스를 가질 수 없으므로이 예제와 같은 뷰를 인덱싱 할 때이 우선 순위를 따르는 방법을 잘 모릅니다.

ConsumableID    ConsumableVariantID AllowThresholdOverwrite FullPath    GroupID ManufacturerID  Type    ModelID
101              29                 1                       0.1.2.4.    4       3               3       2

실제로이 View에서 항상 고유 한 유일한 값은 ConsumableID 열이므로 인덱스를 배치 할 위치를 거의 선택할 수 없습니다.

일반 테이블에서 뷰가 고유하지 않은 클러스터형 인덱스를 허용하지 않는 이유는 무엇입니까?


3
이 페이지 의 맨 아래에는 '뷰의 첫 번째 인덱스를 클러스터링하고 고유해야하는 이유'라는 제목 의 간단한 설명 있습니다. 그러나 그것은 세부 사항을 많이하지 않습니다. 더 자세한 설명을 듣고 싶습니다.
Steve Pettifer

5
몇 가지 의견 : 1-클러스터링 할 수없는 이유는 없습니다 (GroupID, UserID). 키의 단일 열로 제한하지 마십시오. 2-뷰의 한계는 행이 NC 인덱스에 쉽게 묶여 있어야하는 보충 데이터 개체이기 때문이라고 생각합니다. 테이블의 경우 고유하지 않은 CI 키에 정수가 추가되지만 실제 테이블이 아니지만 실제 테이블을 반영해야하기 때문에 인덱싱 된 뷰에서는 더 어려울 것이라고 생각합니다.
JNK

답변:


22

다음은 이 Microsoft 기술 문서 에 설명되어 있습니다 .

뷰의 첫 번째 인덱스를 CLUSTERED하고 고유해야하는 이유는 무엇입니까?

인덱싱 된 뷰 유지 관리 중에 키 값을 사용하여 뷰에서 레코드를 쉽게 조회 할 수 있고 중복 된 뷰를 만들지 못하게하려면 고유해야하며 유지 관리에 특별한 논리가 필요합니다. 클러스터형 인덱스 만 고유성을 적용하고 동시에 행을 저장할 수 있으므로 클러스터링되어야합니다.

SQL Server는 델타 대수 시스템을 사용하여 기본 데이터와 함께 인덱스 된 뷰를 유지합니다. 또한 하나 이상의 인덱싱 된 뷰에 영향을주는 각 DML 쿼리에 대한 뷰 유지 관리 쿼리 계획 연산자를 자동으로 통합합니다. 뷰에 고유 한 클러스터형 인덱스가 있으면 구현 세부 정보가 크게 단순화됩니다.

현재 배열을 사용하면 고정형 유지 관리 운영자 트리 모양을 기본 DML 쿼리 트리에 통합 할 수있어 테스트를 단순화하는 직교성을 제공합니다. 궁극적으로 인덱싱 된 뷰는 비 고유 클러스터형 인덱스를 지원하기 위해 언젠가 향상 될 수 있지만 무제한 시간과 무한한 리소스를 고려할 때 모든 것이 가능합니다.

복잡한 업데이트 쿼리 계획 작성 방법과 미묘한 버그가 쉽게 발생할 수있는 방법을 보여주는 예는MERGE 인덱스 와 함께 발생 하고 필터링 된 인덱스 (인덱싱 된 뷰와 밀접한 관련이있는 기능)에 대한 이 예제를 참조하십시오 .


2
GROUP BY절이 있지만 모든 그룹화 표현식이 클러스터형 인덱스의 키인 것은 아닌 인덱싱 된 뷰를 업데이트하려고하면 비슷한 버그가 발생할 수 있습니다 . SQL Server 2014
Quassnoi

4

SQL Server에서 모든 인덱스 키는 내부적으로 고유해야합니다. 정확히 하나의 행을 처리하는 잠금 키를 확보하는 데 필요합니다. 인덱스 유지 관리에도 필요합니다. 하나의 값만있는 열에서 NCI를 상상해보십시오 (100 % 복제). 테이블에서 행이 삭제되면 스토리지 엔진은 해당 NCI 행을 찾아 삭제해야합니다. 모든 NCI 행을 구별 할 수 없으면 불가능합니다.

따라서 뷰의 CI는 엔진이 작동하기 위해 (내부적으로) 고유해야합니다.

인덱스를 고유하게 만들지 않으면 SQL Server는 여전히 내부적으로 고유하게 만듭니다. 힙 테이블에 NCI가있는 경우 행 책갈피가 추가됩니다. 고유하지 않은 CI의 경우 고유 열을 추가합니다. CI가있는 테이블의 NCI 인 경우, 사용자가 아직 지정하지 않은 CI 키 열을 추가합니다 (유니 쿼 이어가 포함될 수 있음).

인덱싱 된 뷰의 경우 추가 할 수있는 명백한 열이 없습니다. 따라서 SQL Server는이를 자동으로 수행 할 수 없습니다.

일반적으로 뷰에서 CI에 사용할 고유 한 열 집합을 갖도록 추가 할 수있는 열은 사람에게 매우 분명합니다. 이들은 일반적으로 기본 테이블 중 하나의 PK 또는 CI 열입니다. 보기에 GROUP BY일반적으로 그룹화 키를 색인화하십시오.


2
이 답변의 문구를 수정하는 것이 좋습니다. 원래 질문과 관련하여 유효한 요점이 포함되어 있지만 고유하지 않은 모든 인덱스에는 고유자가 포함되어 있지만 그렇지 않은 것으로 보입니다.
spaghettidba

@ spaghettidba 감사합니다, 나는 그것을 알아 차리지 못했습니다. 더 나아 졌으면 좋겠다.
usr

미안, 아직 두 가지를 함께 섞고 있습니다. 비 클러스터형 인덱스는 고유하지 않아도되고 내부적으로 고유하지 않아도됩니다.이 점을 충분히 명확하게 밝히지 않습니다. 답변에서 말하는 모든 내용은 클러스터형 인덱스에만 적용됩니다.
spaghettidba

@spaghettidba NCI는 항상 내부적으로 독특합니다. 항상 모든 CI 키를 쿼리 계획의 일부로 출력 할 수 있습니다. pastebin.com/vkGHpCsR을 참조하십시오 . NCI 데이터 페이지에는 두 개의 열이 있습니다.
usr

어디에서 왔는지 봅니다. 여러 리프가 동일한 인덱스 키를 공유 할 수 있지만 클러스터링 키는 항상 NCI에 포함됩니다. 그들이 항상 내부적으로 독특하다고 말할 수 있습니까? 나는 그렇게 생각하지 않습니다.
spaghettidba
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.