Dlaczego widoki indeksowane nie zezwalają na nieunikalne indeksy klastrowe?

12

Zastanawiałem się nad użyciem widoków indeksowanych, aby zwiększyć wydajność kilku najczęściej używanych widoków.

Widoki indeksowane nie obsługują jednak nieunikalnych indeksów klastrowych, co jest nieco sprzeczne z priorytetem ustawionym przez resztę struktury bazy danych.

Na przykład, oto uproszczona wersja kilku naszych tabel.

-Groups-
Group ID    GroupName

-Users-
UserKey    UserName    FullName     GroupID

Indeksy znajdują się na Groups.GroupID (nieklastrowany) i Users.GroupID (klastrowany). Klucz klastrowany znajdujący się na GroupID w tabeli Users, ponieważ najczęściej pobierany byłby zakres użytkowników z określonej grupy. Oczywiście miałbyś wielu użytkowników na grupę, więc ten indeks klastrowy nie jest unikalny.

To sprawia, że ​​jestem trochę niepewny, jak przestrzegać tego pierwszeństwa podczas indeksowania moich widoków, takich jak ten przykład, ponieważ nie mogę mieć nieunikalnego indeksu klastrowego.

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

W rzeczywistości jedyną wartością w tym widoku, która zawsze byłaby unikalna, jest kolumna ConsumableID, więc nie mam wyboru, gdzie umieścić mój indeks.

Dlaczego widoki nie zezwalają na niejednorodne indeksy klastrowe, gdy robią to zwykłe tabele?

Przyjazny
źródło
3
U dołu tej strony znajduje się bardzo krótkie wyjaśnienie zatytułowane „Dlaczego pierwszy indeks w widoku musi być klastrowany i UNIKALNY?” ale nie robi wiele szczegółów. Na pewno chciałbym usłyszeć bardziej szczegółowe wyjaśnienie.
Steve Pettifer
5
Kilka komentarzy: 1 - Nie ma powodu, dla którego nie można klastrować (GroupID, UserID). Nie ograniczaj się do pojedynczej kolumny dla klucza. 2 - Wyobrażam sobie, że ograniczeniem widoku jest to, że jest to dodatkowy obiekt danych, który musi mieć łatwo powiązane wiersze z indeksami NC. W przypadku tabeli dołączany jest nieunikalny klucz CI, ale myślę, że byłoby to trudniejsze w przypadku widoku indeksowanego, ponieważ nie jest to rzeczywista tabela, ale musi ona ODBRAĆ rzeczywistą tabelę.
JNK

Odpowiedzi:

22

W tym artykule technicznym Microsoft podano następujące wyjaśnienie :

Dlaczego pierwszy indeks w widoku musi być klastrowany i UNIKALNY?

Musi być WYJĄTKOWY, aby umożliwić łatwe wyszukiwanie rekordów w widoku według wartości klucza podczas konserwacji widoku indeksowanego oraz aby zapobiec tworzeniu widoków z duplikatami, których utrzymanie wymagałoby specjalnej logiki. Musi być klastrowany, ponieważ tylko indeks klastrowany może wymusić unikalność i jednocześnie przechowywać wiersze.

SQL Server używa systemu algebry delta, aby utrzymać indeksowane widoki zgodnie z danymi podstawowymi. Automatycznie włącza również operatory planu zapytań konserwacji widoku dla każdego zapytania DML, które wpływa na jeden lub więcej indeksowanych widoków. Posiadanie unikalnego indeksu klastrowego w widoku znacznie upraszcza szczegóły implementacji.

Obecny układ umożliwia włączenie kształtów drzewa operatora konserwacji o stałym kształcie do podstawowego drzewa zapytań DML, zapewniając ortogonalność, która również upraszcza testowanie. Ostatecznie widoki indeksowane mogą zostać ulepszone pewnego dnia, aby obsługiwały nie unikalne indeksy klastrowe, ale z drugiej strony wszystko jest możliwe, biorąc pod uwagę nieograniczony czas i nieograniczone zasoby (z których żadne nie dotyczy zespołu programistów SQL Server w momencie pisania).

Na przykład pokazujący, jak skomplikowane może być budowanie planu zapytania o aktualizację i jak łatwo mogą się wkraść subtelne błędy, zobacz przykład błędu, który występuje z MERGEindeksami indeksowanymi i filtrowanymi (funkcja ściśle powiązana z widokami indeksowanymi).

Paul White 9
źródło
2
Podobny błąd może wystąpić, jeśli spróbujesz zaktualizować indeksowany widok z GROUP BYklauzulą, ale nie wszystkie wyrażenia grupujące są kluczami w indeksie klastrowym. Obowiązuje od SQL Server 2014.
Quassnoi
4

W SQL Server wszystkie klucze indeksu muszą być wewnętrznie unikalne. Jest to wymagane, aby uzyskać klucze blokady, które dotyczą dokładnie jednego wiersza. Jest to również wymagane do utrzymania indeksu. Wyobraź sobie NCI w kolumnie, która ma tylko jedną wartość (100% duplikatów). Jeśli wiersz zostanie usunięty z tabeli, aparat pamięci masowej musi znaleźć odpowiedni wiersz NCI i go również usunąć. Jeśli wszystkie wiersze NCI są nierozróżnialne, byłoby to niemożliwe.

Widzisz więc, że CI w widoku musi być (wewnętrznie) unikalny, aby silnik mógł działać.

Jeśli nie uczynisz indeksu unikalnym, SQL Server nadal czyni go unikalnym wewnętrznie. W przypadku NCI w tabeli stosu dołącza zakładkę wiersza. W przypadku nieunikalnego CI dodaje kolumnę unikalizatora. W przypadku NCI w tabeli z CI dołącza dowolne kolumny kluczy CI, których sam nie określiłeś (może to obejmować unikalizator).

Nie ma oczywistej kolumny, którą można by dołączyć w przypadku widoku indeksowanego. Dlatego SQL Server nie może automatycznie tego zrobić.

Zwykle dla człowieka oczywiste jest, jakie kolumny można dodać, aby widok miał unikalny zestaw kolumn do użycia w CI. Są to zwykle kolumny PK lub CI jednej z podstawowych tabel. Jeśli w widoku znajduje się GROUP BYzwykle indeksowanie kluczy grupowania.

usr
źródło
2
Zdecydowanie sugeruję zmianę sformułowania tej odpowiedzi. Chociaż zawiera on poprawny punkt dotyczący pierwotnego pytania, może się wydawać, że sugeruje, że wszystkie nie unikalne indeksy zawierają unikatory, co nie jest prawdą.
spaghettidba
@spaghettidba dzięki, nie zauważyłem tego. Mam nadzieję, że teraz jest lepiej.
usr
Przepraszam, nie teraz. Mieszacie dwie rzeczy razem. Indeksy nieklastrowane nie muszą być unikalne i nie są jednoznacznie wewnętrznie: nie wyjaśniasz tego wystarczająco jasno. Wszystko, co powiesz w odpowiedzi, dotyczy tylko indeksów klastrowych.
spaghettidba
@spaghettidba NCI są zawsze unikalne wewnętrznie. Zawsze mogą wyprowadzać wszystkie klucze CI jako część planu zapytań. Zobacz pastebin.com/vkGHpCsR Strona danych NCI zawiera obie kolumny.
usr
Widzę skąd pochodzisz. Wiele listków może współdzielić ten sam klucz indeksu, ale klucz klastrowania jest zawsze zawarty w NCI. Czy wystarczy powiedzieć, że zawsze są wyjątkowe wewnętrznie? Nie wydaje mi się
spaghettidba