Pytanie nie brzmi „kiedy PK powinien być NC”, ale zamiast tego należy zapytać „jaki jest właściwy klucz dla indeksu klastrowego”?
Odpowiedź naprawdę zależy od tego, w jaki sposób przeszukujesz dane . Indeks klastrowy ma przewagę nad wszystkimi innymi indeksami: ponieważ zawsze zawiera wszystkie kolumny, zawsze obejmuje. Dlatego zapytania, które mogą wykorzystać indeks klastrowany, z pewnością nie muszą wykorzystywać odnośników do spełnienia niektórych rzutowanych kolumn i / lub predykatów.
Kolejnym elementem układanki jest sposób użycia indeksu ? Istnieją trzy typowe wzory:
- sondy, gdy w indeksie szukana jest pojedyncza wartość klucza
- skanowanie zakresów, gdy pobierany jest zakres wartości kluczowych
- sortuj według wymagań, gdy indeks może spełnić zamówienie, nie wymagając sortowania stop-and-go
Jeśli więc przeanalizujesz oczekiwane obciążenie (zapytania) i odkryjesz, że duża liczba zapytań użyłaby określonego indeksu, ponieważ używają określonego wzorca dostępu, który korzysta z indeksu, warto zaproponować ten indeks jako indeks klastrowany.
Jeszcze innym czynnikiem jest to, że klastrowany klucz indeksu jest kluczem wyszukiwania używanym przez wszystkie nieklastrowane indeksy, a zatem szeroki klastrowany klucz indeksu tworzy efekt falowania i poszerza wszystkie nieklastrowane indeksy, a szerokie indeksy oznaczają więcej stron, więcej operacji we / wy , więcej pamięci, mniej dobroci.
Dobry indeks klastrowany jest stabilny , nie zmienia się w czasie istnienia encji, ponieważ zmiana wartości klucza indeksu klastrowego oznacza, że wiersz musi zostać usunięty i wstawiony z powrotem.
Dobry klastrowany indeks rośnie w kolejności nie losowej (każda nowo wstawiona wartość klucza jest większa niż poprzednia wartość), aby uniknąć podziału strony i fragmentacji (bez bałagania się przy pomocy FILLFACTOR
s).
Skoro już wiemy, co to jest dobry klastrowany klucz indeksu, czy klucz podstawowy (który jest logiczną właściwością modelowania danych) spełnia wymagania? Jeśli tak, to PK powinno być zgrupowane. Jeśli nie, PK powinien być nieklastrowany.
Aby podać przykład, rozważ tabelę faktów sprzedażowych. Każdy wpis ma identyfikator, który jest kluczem podstawowym. Jednak zdecydowana większość zapytań wymaga danych między datą a inną datą, dlatego najlepszym klastrowanym kluczem indeksu byłaby data sprzedaży , a nie identyfikator . Innym przykładem posiadania innego indeksu klastrowego niż klucz podstawowy jest bardzo niski klucz selektywności, taki jak „kategoria” lub „stan”, klucz o bardzo niewielu odrębnych wartościach. Posiadanie klastrowanego klucza indeksu z tym kluczem niskiej selektywności jako kluczem najbardziej na lewo, np. (state, id)
, Często ma sens ze względu na skany zakresów, które szukają wszystkich wpisów w określonym „stanie”.
Ostatnia uwaga na temat możliwości nieklastrowego klucza podstawowego nad stertą (tj. W ogóle nie ma indeksu klastrowanego). Może to być prawidłowy scenariusz, typowym powodem jest krytyczna wydajność wkładki luzem, ponieważ hałdy mają znacznie lepszą przepustowość wkładki luzem w porównaniu z indeksami klastrowymi.
(state, id)
. W tym przykładzie nie zostanie spełniony wymóg „dobry indeks klastrowy rosnący w przypadkowej kolejności”, prawda? Czy możemy zatem uznać to za dobry indeks klastrowy?Podstawowy powód korzystania z indeksów klastrowych jest podany na Wikipedii :
Powiedz, że mam tabelę osób, a ci ludzie mają kolumnę Kraj i unikalny klucz podstawowy. To tabela demograficzna, więc to jedyne rzeczy, na których mi zależy; jaki kraj i ilu wyjątkowych ludzi jest związanych z tym krajem.
W związku z tym mogę tylko WYBRAĆ GDZIE LUB ZAMÓWIENIE WEDŁUG kolumny Kraj; indeks klastrowany na kluczu podstawowym nie robi mi nic dobrego, nie uzyskuję dostępu do tych danych przez PK, uzyskuję do nich dostęp za pośrednictwem tej drugiej kolumny. Ponieważ mogę mieć tylko jeden indeks klastrowany w tabeli, zadeklarowanie mojego PK jako Clustered uniemożliwiłoby mi użycie indeksu klastrowanego w kraju.
Ponadto, tutaj jest dobry artykuł na temat indeksów klastrowanych vs. indeksów nieklastrowanych, okazuje się, że indeksy klastrowe spowodowały problemy z wydajnością wstawiania w SQL Server 6.5 (co, mam nadzieję, nie jest istotne dla większości z nas tutaj).
Pamiętaj, że nie dotyczy to późniejszych wersji.
źródło
Jeśli klucz podstawowy należy do
UNIQUEIDENTIFIER
, należy go podaćNONCLUSTERED
. Jeśli utworzysz klaster, każda wstawka będzie musiała wykonać tasowanie rekordów, aby wstawić nowy wiersz we właściwej pozycji. Spowoduje to wydajność czołgu.źródło
UNIQUEIDENTIFIER
również typ sekwencyjny , który ma takie samo prawdopodobieństwo wygenerowania unikalnych kluczy, choć nadal ma rozmiar 128.Bardzo częsty przykład:
Customer
stół zCustomerID
jakCLUSTERED PRIMARY KEY
OrderID (PK), CustomerID, OrderDate
i innymi kolumnamiOrderPositions
zOrderPositionID (PK), OrderId, ProductID, Amount, Price ...
Oczywiście „to zależy” jest - jak prawie zawsze - poprawną odpowiedzią, ale większość aplikacji (nie raportów BI) będzie działać w oparciu o klienta (np. Zalogujesz się jako klient 278 na stronie i klikniesz „Moje zamówienia” lub sprzedawca wymienia wszystkie zamówienia dla klienta 4569 lub twoja procedura fakturowania sumuje wszystkie zamówienia dla klienta 137).
W takim przypadku nie ma większego sensu grupowanie tabeli według
OrderID
. Tak, będziesz mieć pytaniaSELECT ... WHERE OrderId = ?
dotyczące listy szczegółów zamówienia, ale zwykle będzie to krótki i tani (3 odczyty) indeks szuka.Z drugiej strony, jeśli utworzysz klaster
Order
według tabeliCustomerID
, nie będzie musiał wykonywać wielu odnośników przy każdym zapytaniu o tabelęCustomerId = ?
.CLUSTERED INDEX
Powinno być zawszeUNIQUE
, w przeciwnym razie SQL Server będzie dodać niewidzialny (= bezużyteczny) kolumna INTUNIQUIFIER
zapewnienie uniquiness - i to zrobić dużo więcej sensu, aby dodać Real (użytkowej) danych potem jakiś losowy (w zależności od kolejności wkładania) rzeczy.Ponieważ klient (miejmy nadzieję) złoży więcej niż jedno zamówienie, musielibyśmy dodać albo
OrderID
(lub jeśli zazwyczaj to sortujesz)OrderDate
(jeśli jest to data / godzina - w przeciwnym razie klient byłby ograniczony do jednego zamówienia dziennie) doCLUSTERED INDEX
i kończy się z:CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)
Te same zasady dotyczą
OrderPositions
tabeli. Zwykle większość zapytań zawiera listę wszystkich pozycji dla konkretnego zamówienia, więc powinieneś utworzyć PK zOrderPositionID
asNONCLUSTERED
i aUNIQUE CLUSTERED INDEX
onOrderId, OrderPositionID
.BTW: poprawne jest, że
Customer
tabela jest grupowana według jej PK (CustomerID
ponieważ jest to „Tabela najwyższego poziomu” i będzie - w typowej aplikacji - przeszukiwana przez jej identyfikator klienta.Czyste jak np tablic przeglądowych
Genders
lubInvoiceTypes
czyPaymentType
są kolejnym przykładem tabel, które powinny być skupione przez jego PK (bo będziesz zwykle dołączyć jeGenderId
,InvoiceTypeId
lubPaymentTypeId
).źródło
Gdy indeks klastrowy jest uważany za bardziej korzystny dla całego systemu niż klastrowany PK przy użyciu pewnej miary wydajności. W tabeli może znajdować się tylko jeden indeks klastrowany.
Przykładowe miary wydajności to czas pojedynczego zapytania (szybkość), integracja całkowitych czasów zapytania z tabelą (wydajność) i konieczność dodania wielu kolumn zawierających do bardzo dużego indeksu nieklastrowego, aby osiągnąć wydajność podobną do klastrowanej (rozmiar ).
Może się to zdarzyć, gdy dane są zwykle pobierane przy użyciu indeksu, który nie jest unikalny, zawiera wartości null (niedozwolone w PK) lub PK został dodany z drugiego powodu (takiego jak replikacja lub identyfikacja rekordu ścieżki audytu).
źródło