10

Zazwyczaj indeks klastrowany jest tworzony w programie SQL Server Management Studio, ustawiając klucz podstawowy, jednak moje ostatnie pytanie dotyczące PK < -> indeks klastrowany (Meaning of Primary Key to Microsoft SQL Server 2008) wykazało, że nie jest konieczne ustawianie PK i indeksu klastrowanego na równe.Jak wybrać indeks klastrowany w SQL Server?

Jak zatem wybrać indeksy klastrowe? Rzućmy następujący przykład:

tworzenia tabel Klienci (id int, ...) utworzyć tabeli Orders (id int, int) CustomerID

Chcielibyśmy zwykle utworzyć PK/CI na obu kolumnach identyfikatorów ale pomyślałem o stworzeniu go dla zamówień w CustomerID. Czy to najlepszy wybór?

+0

Możliwy duplikat [Serwer SQL - kiedy należy korzystać z indeksu klastrowego a nie klastrowanego?] (Https://stackoverflow.com/questions/18304376/sql-server-when-to-use-clustered-vs-non- indeks klastrowy) –

Odpowiedz

11

Według Królowa indeksowania - Kimberly Tripp - co ona szuka w indeksie klastrowym to przede wszystkim:

  • Unikalne
  • Narrow
  • Static

A jeśli możesz również zagwarantować:

  • Wzrastający wzór

to bardzo blisko posiadania idealnego klucza do klastrowania!

Zapoznaj się z jej całą wersją blog post here i kolejną naprawdę interesującą kwestią dotyczącą grupowania kluczowych wpływów na operacje w tabeli tutaj: The Clustered Index Debate Continues.

Wszystko jak INT (szczególnie INT IDENTITY) lub ewentualnie INT i DATETIME są idealnymi candiates. Z innych powodów GUID nie są dobrymi kandydatami - możesz więc mieć identyfikator GUID jako swój PK, ale nie grupuj go na swoim stole - będzie to fragmentacja nie do poznania, a wydajność ucierpi.

+0

Czy te wpisy na blogu są nadal tak samo istotne dla nowszych wersji SQL Server, czy też najnowsze poprawki wydajności w SQL Server 2008 i później zmieniły jakoś najlepsze praktyki? –

+0

@AdrianGrigore: wszystko jest nadal poprawne, o ile używasz "normalnych" tabel (np. Nie ma datawarehouse/columnstore) –

+0

Świetne, dzięki! :) –

1

Jeśli obawiasz się klastrowania, zazwyczaj pomaga to w poprawie pobierania danych. Na przykład, prawdopodobnie będziesz chciał wszystkie rekordy dla danego klienta na raz. Utworzenie klauzuli customerID spowoduje, że wiersze będą przechowywane na tej samej stronie fizycznej, a nie rozproszone na wielu stronach w pliku.

ROT: Klastra, na którym chcesz pokazać kolekcję. Elementy zamówienia w zamówieniu to klasyczny przykład.

+0

Elementy zamówienia w zamówieniu mogą być dobrym pomysłem dla klastra, ale nie, jeśli w typowej kolejności są tylko 2 lub 3 (lub kilkanaście) elementów zamówienia. O ile wiersze, które klastry nie łączą się razem, zaczynają docierać do dziesiątek lub setek, lepiej jest pozwolić serwerowi SQL na wykonanie wyszukiwania zakładek. Miałem system, w którym wymagania biznesowe musiały znaleźć wszystkie "elementy zamówienia", które miały miejsce podczas danej zmiany kasjera (aby sprawdzić, czy są zrównoważone). Denormalizacja "elementów zamówienia" z "id", jeśli ** Shift **, a następnie klastrowanie na ** Shift ** było ogromnym wzrostem prędkości. –

6

Najlepszym kandydatem do indeksu CLUSTERED jest klucz, którego używasz najczęściej w swoich zapisach.

Zazwyczaj jest to PRIMARY KEY, ponieważ jest używany w wyszukiwaniach i/lub relacjach FOREIGN KEY.

W twoim przypadku najprawdopodobniej udział w wyszukiwaniu i referencjach będzie mieć Orders.ID, więc jest to najlepszy kandydat do bycia wyrażeniem skupiającym.

Jeśli utworzyć indeks CLUSTERED na Orders.CustomerID następujące rzeczy się wydarzy:

  1. CustomerID nie jest wyjątkowa. Aby zapewnić wyjątkowość, do każdego rekordu zostanie dodana specjalna ukryta kolumna 32-bit znana jako uniquifier.

  2. Zapisy w tabeli będą przechowywane zgodnie z tą parą kolumn (CustomerID, uniquifier).

  3. Utworzony zostanie indeks wtórny na Order.ID, z indeksem rekordów jako (CustomerID, uniquifier).

  4. Zapytania takie jak ten:

    SELECT * 
    FROM Orders 
    WHERE ID = 1234567 
    

    trzeba robić operację zewnętrznego, a Clustered Seek, ponieważ nie wszystkie kolumny są przechowywane w indeksie na ID. Aby pobrać wszystkie kolumny, rekord powinien najpierw znajdować się w tabeli klastrowej.

Ta dodatkowa operacja wymaga IndexDepth aż strona odczytuje jako prosty Clustered Seek The IndexDepth beign O(log(n)) ogólnej liczby rekordów w tabeli.