클러스터형 인덱스 선택-PK 또는 FK?


11

나는이 SQL 서버 2014 표를 그 다음과 같습니다 :

OrderId     int           not null IDENTITY --this is the primary key column
OrderDate   datetime2     not null
CustomerId  int           not null
Description nvarchar(255) null

우리 팀의 일부 사람들은 클러스터 된 인덱스가 on이어야한다고 제안 OrderId했지만 다음과 같은 이유로 CustomerId+ OrderId가 더 나은 선택 이라고 생각합니다 .

  • 거의 모든 쿼리를 찾는 것 WHERE CustomerId = @param,하지OrderId
  • CustomerIdCustomer테이블에 대한 외래 키 이므로 클러스터형 인덱스를 사용 CustomerId하면 조인 속도가 빨라집니다.
  • 하지만 CustomerId고유하지 않습니다, 추가적인 가진 OrderId인덱스에 지정된 열은 (우리가 사용할 수있는 고유성을 보장합니다 UNIQUE그 2 열에 클러스터 된 인덱스를 만들 때 고유성을 가지고 있지의 오버 헤드를 피하기 위해, 키워드)
  • 데이터가 삽입되면 CustomerIdand가 OrderId변경되지 않으므로이 행은 초기 쓰기 후에 움직이지 않습니다.
  • 데이터 액세스는 기본적으로 모든 열을 요청하는 ORM을 통해 이루어 지므로, 기반 쿼리가 CustomerId들어 오면 클러스터 된 인덱스는 추가 작업없이 모든 열을 제공 할 수 있습니다.

CustomerIdOrderId접근 방식이 위의 최상의 옵션처럼 들립니까 ? 또는 OrderId독창성을 보장하는 단일 열이기 때문에 자체적으로 더 나은가요?

현재 테이블에는 클러스터 된 인덱스가 있고 클러스터 OrderId되지 않은 인덱스는 있습니다 CustomerId. 그러나 다루지 않으므로 ORM을 사용하고 있고 모든 열이 요청되었으므로이를 검색하는 추가 작업이 필요합니다. 이 게시물을 통해 더 나은 CI로 성능을 개선하려고합니다.

DB의 활동은 약 85 % 읽기 및 15 % 쓰기입니다.

답변:


5

커뮤니티 위키 답변 :

첫 번째 열이 CustomerID 인 복합 클러스터형 인덱스 키가 WHERE거의 모든 쿼리 의 절에 있기 때문에 가장 좋습니다 .

증분 키와 비교할 때 더 많은 분할이있을 수 있습니다 (또는 '나쁜'분할을 피하기 위해 채우기 비율관리하고 유지하는 경우 시간에 따라 최적이 아닌 페이지 밀도가 더 높아질 수 있습니다 ). 그러나 주요 조회를 피할 수 있기 때문에 고객 쿼리에 대한 전반적인 성능 향상이 상당합니다.

가장 중요한 쿼리에 따라 OrderID 또는 OrderDate 가 두 번째 열에 가장 적합 할 수 있습니다.

예를 들어, 고객이 웹 사이트에 로그인 한 후 최근 주문의 시간순 목록을 볼 경우 OrderDate 가 다음에 있어야 최적화 할 수 있습니다 ORDER BY OrderDate DESC.

CustomerID 에 비 클러스터형 인덱스가있는 클러스터형 인덱스로 OrderID 를 선택 하면 비 클러스터형 인덱스 에서도 여전히 분할 및 조각화가 발생합니다.


3

이 테이블이 쓰기 집약적이라면 (예를 들어, 테이블에 대한 INSERT진술 보다 더 많은 진술이 발생하는 경우 SELECT) 위키 답변 에 동의하지 않을 입니다.

복합 클러스터 키의 첫 번째 열로 CustomerID를 선택하면 많은 중간 페이지 분할이 생성 됩니다. 기존 고객이 많으면서도 많은 신규 고객이 항상 있기를 바랍니다. 비즈니스가 계속 성장함에 따라 고객이 여러 주문을 (희망적으로) 주문하고 있기 때문에,이 접근 방식은 상당한 양의 중간 페이지 분할을 보여 쓰기에 대한 성능뿐만 아니라 인덱스가 크게 조각화 될 수 있습니다. 더 많은 양의 공백이있을 수 있습니다 (저장소 및 메모리 낭비를 의미 함).

CustomerID가 복합 클러스터형 인덱스의 선행 열이어야한다고 생각되면 FILLFACTOR이 테이블의 모든 인덱스를 조정 하여 페이지 중간 분할의 영향을 줄일 수 있습니다 . 테이블 / 인덱스의 크기를 늘려 페이지 중간 분할 크기를 줄입니다. 이 경로를 사용하려면 80 값으로 테스트하고 페이지 중간 분할이 여전히 성능을 저하 시키는 것으로 분석 된 경우 감소시키는 것이 좋습니다 .

내 제안은 OrderId를 사용하는 것입니다. OrderID는 당연히 순차적이어야하고 테이블 증가에 따라 양호하고 예상되는 끝 페이지 분할을 더 많이 생성해야합니다. 또한 OrderDate 열을 파티션 키로 사용하도록 선택한 경우이 방법은 테이블 파티셔닝 에서 더 잘 작동합니다. 지속적으로 CustomerID 필드를 사용하는 쿼리와 관련하여 해당 쿼리를 처리 할 비 클러스터형 인덱스를 만듭니다. 이 인덱스는 FILLFACTOR위에서 언급 한 중간 페이지 분할로 인해 발생할 수 있으므로 적절한 것으로 정의해야 하지만 클러스터 된 인덱스에 대해 분할이 발생한 경우와 비교하여 전체적으로 나쁘지는 않습니다.

DB의 활동은 약 85 % 읽기 및 15 % 쓰기입니다.

CustomerID+ OrderID(그리고 분할없이 성장할 수 있도록 채우기 비율을 지정하는 것)은 아마도 그 평가가 사실이라면 더 나을 것입니다. 그냥 만들 있는지 평가가 정확하다는 것을. 테스트 테스트 테스트.


1
페이지에서 마지막 (또는 유일한) 고객에 대한 주문을 삽입하는 것은 "중간 페이지 분할"이 아닙니다. 따라서 고객 당 주문이 많거나 행 너비가 큰 경우 더 적은 주문 삽입에 "중간 페이지 분할"이 필요합니다.
David Browne-Microsoft
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.