Słyszałem, że na początku deklaracji indeksu należy umieścić kolumny, które będą najbardziej selektywne. Przykład:
CREATE NONCLUSTERED INDEX MyINDX on Table1
(
MostSelective,
SecondMost,
Least
)
Po pierwsze, czy to, co mówię, jest poprawne? Jeśli tak, czy prawdopodobnie zauważę duże różnice w wydajności, zmieniając kolejność kolumn w moim indeksie, czy też jest to bardziej „przyjemna do zrobienia” praktyka?
Pytam dlatego, że po wysłaniu zapytania przez DTA zaleciłem utworzenie indeksu, który miałby prawie wszystkie te same kolumny, co istniejący indeks, tylko w innej kolejności. Rozważałem po prostu dodanie brakujących kolumn do istniejącego indeksu i nazwanie go dobrze. Myśli?
źródło
Kolejność kolumn jest krytyczna. Teraz, która kolejność jest poprawna, zależy od tego, jak zamierzasz o nie zapytać. Indeks może służyć do dokładnego przeszukiwania lub skanowania zakresu. Dokładne przeszukiwanie ma miejsce, gdy określone są wartości dla wszystkich kolumn w indeksie, a zapytanie ląduje dokładnie w interesującym nas wierszu. W przypadku wyszukiwania kolejność kolumn nie ma znaczenia. Skanowanie zakresu ma miejsce, gdy określone są tylko niektóre kolumny, w tym przypadku, gdy kolejność staje się ważna. SQL Server może używać indeksu do skanowania zakresu tylko wtedy, gdy określono skrajną lewą kolumnę i tylko wtedy, gdy określono następną skrajną lewą kolumnę i tak dalej. Jeśli masz indeks na (A, B, C), można go użyć do przeszukiwania zakresu w poszukiwaniu
A=@a
,A=@a AND B=@b
ale nie w poszukiwaniuB=@b
, w poszukiwaniuC=@c
norB=@b AND C=@c
. SprawaA=@a AND C=@c
jest mieszana, jak wA=@a
część użyje indeksu, aleC=@c
nie (zapytanie przeskanuje wszystkie wartości BA=@a
, nie przeskoczy doC=@c
). Inne systemy bazodanowe mają tak zwany operator „skip scan”, który może w pewnym stopniu wykorzystać wewnętrzne kolumny w indeksie, gdy kolumny zewnętrzne nie są określone.Mając tę wiedzę, możesz ponownie przyjrzeć się definicjom indeksu. Indeks włączony
(MostSelective, SecondMost, Least)
będzie obowiązywał tylko wtedy, gdyMostSelective
określono kolumnę. Ale ponieważ jest to najbardziej selektywne, znaczenie wewnętrznych kolumn szybko się zmniejszy. Bardzo często okaże się, że lepszy indeks jest włączony(MostSelective) include (SecondMost, Least)
lub włączony(MostSelective, SecondMost) include (Least)
. Ponieważ kolumny wewnętrzne są mniej istotne, umieszczenie kolumn o niskiej selektywności we właściwych pozycjach w indeksie sprawia, że są one niczym innym jak hałasem podczas wyszukiwania, dlatego sensowne jest przeniesienie ich ze stron pośrednich i pozostawienie ich tylko na stronach liści, ponieważ zapytania dotyczące pokrycia. Innymi słowy, przenieś je do INCLUDE. Staje się to ważniejsze wraz ze wzrostem rozmiaruLeast
kolumny. Chodzi o to, że ten indeks może przynieść korzyści tylko zapytaniom, które określająMostSelective
albo jako dokładna wartość, albo jako zakres, a ta kolumna jest najbardziej selektywna, ogranicza już w dużym stopniu wiersze kandydatów.Z drugiej strony indeks na
(Least, SecondMost, MostSelective)
może wydawać się błędem, ale w rzeczywistości jest to dość silny indeks. Ponieważ maLeast
kolumnę jako najbardziej zewnętrzne zapytanie, może być używane do zapytań, które muszą agregować wyniki w kolumnach o niskiej selektywności. Takie zapytania są powszechne w OLAP i hurtowniach danych analitycznych i właśnie w tym przypadku takie indeksy mają bardzo dobre uzasadnienie. Takie indeksy w rzeczywistości stanowią doskonałe indeksy klastrowe , właśnie dlatego, że organizują fizyczny układ na dużych fragmentach powiązanych wierszy (ta samaLeast
wartość, która zwykle wskazuje na jakąś kategorię lub typ) i ułatwiają zapytania analityczne.Tak więc niestety nie ma „właściwej” kolejności. Nie powinieneś przestrzegać żadnego przepisu na obcinanie ciasteczek, ale zamiast tego przeanalizuj wzorzec zapytania, którego zamierzasz użyć w tych tabelach i zdecyduj, która kolejność kolumn indeksu jest właściwa.
źródło
Jak mówi Remus, zależy to od obciążenia pracą.
Chcę jednak odnieść się do mylącego aspektu przyjętej odpowiedzi.
W przypadku zapytań, które wykonują wyszukiwanie według równości we wszystkich kolumnach indeksu, nie ma znaczącej różnicy.
Poniższe tworzy dwie tabele i wypełnia je identycznymi danymi. Jedyna różnica polega na tym, że jeden ma klucze w kolejności od najbardziej do najmniej selektywnej, a drugi odwrotnie.
Teraz wykonuję zapytanie względem obu tabel ...
... Obaj stosują indeksową grzywnę i obaj otrzymują dokładnie ten sam koszt.
Sztuka ASCII w przyjętej odpowiedzi nie jest w rzeczywistości strukturą indeksów. Poniżej przedstawiono strony indeksu dla tabeli 1 (kliknij obraz, aby otworzyć w pełnym rozmiarze).
Strony indeksowe zawierają wiersze zawierające cały klucz (w tym przypadku w rzeczywistości jest dodana dodatkowa kolumna klucza dla identyfikatora wiersza, ponieważ indeks nie został zadeklarowany jako unikalny, ale można go pominąć, więcej informacji na ten temat można znaleźć tutaj ).
W przypadku zapytania powyżej SQL Server nie dba o selektywność kolumn. Czyni binarne przeszukiwanie strony i odkrywa, że głównym Key
(PPP...,3,~ )
jest>=(JJJ...,1,~ )
i< (SSS...,3,~ )
tak powinno czytać strony1:118
. Następnie wyszukuje binarnie kluczowe wpisy na tej stronie i lokalizuje stronę liścia, do której ma przejść.Zmiana indeksu w kolejności selektywności nie wpływa ani na oczekiwaną liczbę kluczowych porównań z wyszukiwania binarnego, ani na liczbę stron, po których należy przejść, aby przeszukać indeks. W najlepszym wypadku może nieznacznie przyspieszyć samo porównanie kluczy.
Czasami jednak pierwsze zamówienie indeksu najbardziej selektywnego ma sens w przypadku innych zapytań w obciążeniu.
Np. Jeśli obciążenie zawiera zapytania z obu poniższych formularzy.
Powyższe indeksy nie obejmują żadnego z nich.
MostSelective
jest wystarczająco selektywny, aby plan z wyszukiwaniem i wyszukiwaniem był opłacalny, ale zapytanie przeciwkoLeast
nie jest.Jednak ten scenariusz (nieobejmujące przeszukiwanie indeksu w podzbiorze wiodących kolumn indeksu złożonego) jest tylko jedną możliwą klasą zapytania, w której może pomóc indeks. Jeśli nigdy nie wyszukujesz
MostSelective
samodzielnie lub w połączeniu zMostSelective, SecondMost
i zawsze wyszukujesz według kombinacji wszystkich trzech kolumn, ta teoretyczna zaleta jest dla Ciebie bezużyteczna.I odwrotnie zapytania, takie jak
Pomogłoby to w odwrotnej kolejności do powszechnie zalecanej - ponieważ obejmuje zapytanie, może obsługiwać wyszukiwanie i zwraca wiersze w pożądanej kolejności do uruchomienia.
Więc jest to często powtarzana rada ale co najwyżej jest to heurystyczny o potencjalne korzyści dla innych zapytań - i to nie zastąpi faktycznie patrząc na twoją pracą.
źródło
Poprawny. Indeksy mogą być złożone - złożone z wielu kolumn - a kolejność jest ważna ze względu na zasadę znajdującą się najbardziej po lewej stronie. Powodem jest to, że baza danych sprawdza listę od lewej do prawej i musi znaleźć odpowiednie odwołanie do kolumny pasujące do zdefiniowanej kolejności. Na przykład posiadanie indeksu w tabeli adresów z kolumnami:
Każde zapytanie korzystające z
address
kolumny może korzystać z indeksu, ale jeśli zapytanie ma tylko odwołania albocity
i / lubstate
- indeks nie może zostać użyty. Dzieje się tak, ponieważ nie ma odniesienia do skrajnej lewej kolumny. Wydajność zapytania powinna wskazywać, która z nich jest optymalna - poszczególne indeksy lub wiele elementów złożonych o różnych zamówieniach. Dobra lektura: Punkt krytyczny autorstwa Kimberley Trippźródło
Wszystkie inne odpowiedzi są błędne.
Selektywność poszczególnych kolumn w indeksie złożonym nie ma znaczenia przy kompletacji zamówienia.
Oto prosty proces myślowy: w rzeczywistości indeks to konkatenacja odpowiednich kolumn.
Dając to uzasadnienie, jedyną różnicą jest porównanie dwóch „łańcuchów”, które różnią się wcześniej i później w ciągu. To niewielka część całkowitego kosztu. Nie ma „pierwszego przebiegu / drugiego przejścia”, jak wspomniano w jednej odpowiedzi.
Więc jaką kolejność należy zastosować?
=
w dowolnej kolejności.Na przykład kolumna bardzo niska selektywność musi być w tym przypadku pierwsza:
Zamiana kolejności w indeksie spowodowałaby całkowite zignorowanie
deleted
.(Istnieje znacznie więcej reguł dotyczących kolejności kolumn).
źródło
deleted
nie pomaga zbytnio w filtrowaniu niechcianych wierszy. Czy masz lepszy przykład? (To ten, który przyszedł mi do głowy, kiedy napisałem odpowiedź.)