it-swarm.dev

Kiedy klucz podstawowy należy zadeklarować jako nieklastrowany?

Tworząc testową bazę danych dla innego pytania, które zadałem wcześniej, przypomniałem sobie, że klucz podstawowy można zadeklarować NONCLUSTERED

Kiedy użyjesz klucza podstawowego NONCLUSTERED zamiast klucza podstawowego CLUSTERED?

Z góry dziękuję

177
Stuart Blackler

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 jak zapytać o 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ą używać odnośników do spełnienia niektórych rzutowanych kolumn i/lub predykatów.

Kolejnym elementem układanki jest jak można użyć indeks? 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 indeksy nieklastrowane, a zatem szeroki indeks klucza klastrowego tworzy efekt tętnienia i rozszerza wszystkie indeksy nieklastrowane i szerokie indeksy oznaczają więcej stron, więcej I/O, więcej pamięci, mniej dobroci.

Dobry indeks klastrowany to 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 indeks klastrowy 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łaganu z FILLFACTORs).

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 sprzedaż data, a nie ID . 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 skanowanie zakresów, które wyszukują wszystkie wpisy w określonym „stanie”.

Ostatnia uwaga na temat możliwości nieklastrowego klucza podstawowego nad stertą (tzn. 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.

194
Remus Rusanu

Podstawowy powód korzystania z indeksów klastrowych podano na Wikipedia :

Klastrowanie zmienia blok danych w pewną odrębną kolejność w celu dopasowania do indeksu, w wyniku czego dane wiersza są przechowywane w kolejności. Dlatego w danej tabeli bazy danych można utworzyć tylko jeden indeks klastrowy. Indeksy klastrowe mogą znacznie zwiększyć ogólną szybkość wyszukiwania, ale zwykle tylko , gdy dane są dostępne sekwencyjnie w tym samym lub odwrotna kolejność indeksu klastrowego lub po wybraniu zakresu elementów.

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, oto dobry artykuł na temat Indeksy klastrowane vs. indeksy klastrowane , 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).

Jeśli umieścisz indeks klastrowany w kolumnie TOŻSAMOŚĆ, wówczas wszystkie twoje wstawki pojawią się na ostatniej stronie tabeli - i ta strona jest zablokowana na czas trwania każdej TOŻSAMOŚCI. Nic wielkiego ... chyba że masz 5000 osób, które chcą ostatniej strony. Masz dużo sporów o tę stronę

Pamiętaj, że nie dotyczy to późniejszych wersji.

27
Ben Brocka

Jeśli klucz podstawowy należy do UNIQUEIDENTIFIER, upewnij się, że jest to 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.

17
Bryan Johns

Bardzo częsty przykład:

  • Tabela Customer z CustomerID jako CLUSTERED PRIMARY KEY
  • Porządkuj tabelę z OrderID (PK), CustomerID, OrderDate i kilkoma innymi kolumnami
  • OrderPositions z OrderPositionID (PK), OrderId, ProductID, Amount, Price ...
  • musisz zaindeksować tabele zamówień

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ć zapytania jako SELECT ... WHERE OrderId = ?, Aby wyświetlić szczegóły zamówienia, ale zwykle będzie to krótki i tani (3 odczyty) indeks szuka.

Z drugiej strony, jeśli klaster tabeli Order zostanie zgrupowany według CustomerID, nie będzie musiał wykonywać wielu wyszukiwań klucza za każdym razem, gdy zapytasz tabelę o CustomerId = ?.

CLUSTERED INDEX Powinien zawsze mieć wartość UNIQUE, w przeciwnym razie SQL Server dodałby niewidoczną (= nieużywalną) kolumnę INT UNIQUIFIER, aby zapewnić wyjątkowość - i sensowniej byłoby dodać prawdziwe (użyteczne) dane, a następnie losowe (w zależności od kolejności wstawiania) rzeczy.

Ponieważ klient (miejmy nadzieję) złoży więcej niż jedno zamówienie, musielibyśmy dodać albo OrderID, albo (jeśli zwykle to sortujesz) OrderDate (jeśli jest to data/godzina - inaczej klient będzie ograniczony do jednego zamówienia dziennie) do CLUSTERED INDEX i kończy się na:

CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)

Te same zasady dotyczą tabeli OrderPositions. Zwykle większość zapytań zawiera listę wszystkich pozycji dla określonej kolejności, dlatego powinieneś utworzyć PK z OrderPositionID jako NONCLUSTERED i UNIQUE CLUSTERED INDEX W OrderId, OrderPositionID.

BTW: słuszne jest, że tabela Customer jest grupowana według jej PK (CustomerID, ponieważ jest to „Tabela najwyższego poziomu” i - w typowej aplikacji - jest w większości pytana przez jego identyfikator klienta.

Tabele czystego wyszukiwania, np. Genders lub InvoiceTypes lub PaymentType to kolejny przykład tabel, które powinny być grupowane przez jego PK (ponieważ zwykle dołączasz do nich w GenderId, InvoiceTypeId lub PaymentTypeId).

8
Thomas Franz

Gdy indeks klastrowy jest uważany za bardziej korzystny dla całego systemu niż klastrowany PK, stosując pewną miarę 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 w celu osiągnięcia wydajności zbliżonej do klastrowej (rozmiar ).

Może się to zdarzyć, gdy dane są ogólnie 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 śladu audytu).

2
crokusek