Jakie kolumny generalnie są dobrymi indeksami?

98

W ramach kontynuacji sekcji „ Co to są indeksy i jak mogę ich używać do optymalizacji zapytań w mojej bazie danych? ”, W której próbuję dowiedzieć się więcej o indeksach, jakie kolumny są dobrymi kandydatami na indeksy? Specjalnie dla bazy danych MS SQL?

Po pewnym googlowaniu wszystko, co przeczytałem, sugeruje, że kolumny, które generalnie rosną i są unikalne, tworzą dobry indeks (rzeczy takie jak auto_increment MySQL), rozumiem to, ale używam MS SQL i używam identyfikatorów GUID dla kluczy głównych, więc wydaje się że indeksy nie przyniosą korzyści dla kolumn GUID ...

mmattax
źródło
Co powiesz na „książkę kucharską”: mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Odpowiedzi:

110

Indeksy mogą odgrywać ważną rolę w optymalizacji zapytań i szybkim wyszukiwaniu wyników w tabelach. Dlatego najważniejszym krokiem jest wybranie kolumn do indeksowania. Istnieją dwa główne miejsca, w których możemy rozważyć indeksowanie: kolumny, do których odwołuje się klauzula WHERE i kolumny używane w klauzulach JOIN. Krótko mówiąc, takie kolumny powinny być indeksowane, według których musisz przeszukiwać określone rekordy. Załóżmy, że mamy tabelę o nazwie buyers, w której zapytanie SELECT używa indeksów takich jak poniżej:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Ponieważ w części SELECT występuje odniesienie do „Buyer_id”, MySQL nie użyje go do ograniczenia wybranych wierszy. Dlatego nie ma wielkiej potrzeby indeksowania. Poniżej znajduje się kolejny przykład nieco różniący się od powyższego:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Zgodnie z powyższymi zapytaniami first_name kolumny last_name mogą być indeksowane, ponieważ znajdują się w klauzuli WHERE. Można również wziąć pod uwagę dodatkowe pole country_id z tabeli krajów, ponieważ znajduje się ono w klauzuli JOIN. Zatem indeksowanie można rozpatrywać w każdym polu w klauzuli WHERE lub w klauzuli JOIN.

Poniższa lista zawiera również kilka wskazówek, o których należy zawsze pamiętać podczas tworzenia indeksów w tabelach:

  • Indeksuj tylko te kolumny, które są wymagane w klauzulach WHERE i ORDER BY. Indeksowanie kolumn w dużej liczbie spowoduje pewne wady.
  • Spróbuj skorzystać z funkcji MySQL „przedrostek indeksu” lub „indeks wielu kolumn”. Jeśli tworzysz indeks, taki jak INDEX (imię, nazwisko), nie twórz INDEKSU (imię). Jednak „przedrostek indeksu” lub „indeks z wieloma kolumnami” nie są zalecane we wszystkich przypadkach wyszukiwania.
  • Użyj atrybutu NOT NULL dla tych kolumn, w których rozważasz indeksowanie, aby wartości NULL nigdy nie były przechowywane.
  • Użyj opcji --log-long-format, aby rejestrować zapytania, które nie używają indeksów. W ten sposób możesz sprawdzić ten plik dziennika i odpowiednio dostosować swoje zapytania.
  • Instrukcja EXPLAIN pomaga ujawnić, w jaki sposób MySQL wykona zapytanie. Pokazuje, jak iw jakiej kolejności są łączone tabele. Może to być bardzo przydatne do określania, jak pisać zoptymalizowane zapytania i czy kolumny mają być indeksowane.

Aktualizacja (23 lutego 2015):

Każdy indeks (dobry / zły) wydłuża czas wstawiania i aktualizacji.

W zależności od posiadanych indeksów (liczby indeksów i typu) wyszukiwany jest wynik. Jeśli czas wyszukiwania wydłuży się z powodu indeksu, to jest to zły indeks.

Prawdopodobnie w każdej książce „Strona indeksu” może mieć stronę początkową rozdziału, początek numeru strony tematu, a także początek strony tematu podrzędnego. Pewne wyjaśnienia na stronie indeksu mogą pomóc, ale bardziej szczegółowy indeks może cię zmylić lub przestraszyć. Indeksy również mają pamięć.

Wybór indeksu powinien być mądry. Pamiętaj, że nie wszystkie kolumny wymagają indeksu.

Somnath Muluk
źródło
Dzięki Somnath, więc czy to oznacza, że ​​indeksy powinny być tworzone tylko dla kolumn, w których planujemy użyć WHERE, JOINSczy HAVING?
Muhammad Babar
3
Tak, użyj indeksów dla kolumn, w których planujesz użyć WHERE, JOINS lub HAVING. Pamiętaj jednak, że wszystkie kolumny warunków nie wymagają indeksów. Czasami kolumna warunku jest używana tylko raz, więc może nie potrzebować indeksu, podczas gdy inna kolumna warunku jest używana w wielu zapytaniach, więc wolisz więcej do indeksowania do tej kolumny.
Somnath Muluk
1
Odpowiedź skorzystałaby na umieszczeniu „kolumn przywoływanych w klauzuli WHERE i kolumn używanych w klauzulach JOIN” w sekcji TL; DR.
jpmc26
Więc mówisz, że jeśli w mojej WHEREklauzuli sprawdzam wartość pola, w którym jego kolumna może przyjmować tylko dwie wartości, to powinienem indeksować tę kolumnę binarną? Wydaje się to niewłaściwe.
AjaxLeung,
@AjaxLeung: Pamiętaj o maksymie Knutha „Przedwczesna optymalizacja jest źródłem wszelkiego zła”. Możesz zrobić indeks na kolumnach binarnych, ale powinno to zależeć od tego, jakim kosztem (np. Wstawianie, czasy aktualizacji). Jeśli logika biznesowa często zależy od tego przełącznika binarnego, może być wymagana kolumna binarna z indeksem.
Somnath Muluk
20

Niektórzy ludzie odpowiedzieli tutaj na podobne pytanie: Skąd wiesz, co to jest dobry indeks?

Zasadniczo zależy to od tego, w jaki sposób będziesz sprawdzać dane. Potrzebujesz indeksu, który szybko identyfikuje niewielki podzbiór zbioru danych, który ma znaczenie dla zapytania. Jeśli nigdy nie wykonujesz zapytania według sygnatury daty, nie potrzebujesz indeksu, nawet jeśli jest on w większości unikalny. Jeśli wszystko, co robisz, to otrzymywanie wydarzeń, które miały miejsce w określonym zakresie dat, na pewno chcesz je mieć. W większości przypadków indeks płci jest bezcelowy - ale jeśli wszystko, co robisz, to uzyskiwanie statystyk dotyczących wszystkich mężczyzn i osobno wszystkich kobiet, może warto poświęcić chwilę, aby je utworzyć. Dowiedz się, jakie będą wzorce zapytań i uzyskaj dostęp do tego, który parametr najbardziej zawęża przestrzeń wyszukiwania, a to jest twój najlepszy indeks.

Weź również pod uwagę rodzaj indeksu, który tworzysz - B-drzewa są dobre dla większości rzeczy i pozwalają na zapytania o zakresy, ale indeksy hash prowadzą od razu do celu (ale nie zezwalaj na zakresy). Inne typy indeksów mają inne zalety i wady.

Powodzenia!

SquareCog
źródło
9

Wszystko zależy od tego, jakie zapytania spodziewasz się zapytać o tabele. Jeśli poprosisz o wszystkie wiersze z określoną wartością w kolumnie X, będziesz musiał wykonać pełne skanowanie tabeli, jeśli nie można użyć indeksu.

Indeksy będą przydatne, jeśli:

  • Kolumna lub kolumny mają wysoki stopień wyjątkowości
  • Często trzeba szukać określonej wartości lub zakresu wartości dla kolumny.

Nie będą przydatne, jeśli:

  • Wybierasz duży% (> 10–20%) wierszy w tabeli
  • Dodatkowe wykorzystanie przestrzeni jest problemem
  • Chcesz zmaksymalizować wydajność płytki. Każdy indeks w tabeli zmniejsza wydajność wstawiania i aktualizowania, ponieważ muszą one być aktualizowane za każdym razem, gdy zmieniają się dane.

Kolumny klucza podstawowego są zwykle doskonałe do indeksowania, ponieważ są unikalne i często są używane do wyszukiwania wierszy.

Plasmer
źródło
wyszukiwanie ciągów znaków, w których wartość może znajdować się w dowolnym miejscu w ciągu, może sprawić, że nie użyje w tym przypadku tych indeksów.
Arthur Thomas,
5

Ogólnie (nie używam mssql, więc nie mogę komentować), klucze podstawowe tworzą dobre indeksy. Są unikalne i muszą mieć określoną wartość. (Ponadto klucze podstawowe są tak dobrymi indeksami, że zwykle mają indeks utworzony automatycznie).

Indeks jest faktycznie kopią kolumny, która została posortowana, aby umożliwić wyszukiwanie binarne (które jest znacznie szybsze niż wyszukiwanie liniowe). Systemy baz danych mogą wykorzystywać różne sztuczki, aby jeszcze bardziej przyspieszyć wyszukiwanie, szczególnie jeśli dane są bardziej złożone niż prosta liczba.

Sugerowałbym, aby początkowo nie używać żadnych indeksów i profilować zapytania. Jeśli określone zapytanie (na przykład wyszukiwanie osób według nazwiska) jest uruchamiane bardzo często, spróbuj ponownie utworzyć indeks dla odpowiednich atrybutów i profilu. Jeśli zauważalne jest przyspieszenie zapytań i nieznaczne spowolnienie wstawiania i aktualizacji, zachowaj indeks.

(Przepraszam, jeśli powtarzam rzeczy wymienione w Twoim drugim pytaniu, nie spotkałem się z tym wcześniej).

Zooba
źródło
5

Każda kolumna, która będzie regularnie używana do wyodrębniania danych z tabeli, powinna być zindeksowana.

Obejmuje to: klucze obce -

select * from tblOrder where status_id=:v_outstanding

pola opisowe -

select * from tblCust where Surname like "O'Brian%"

Kolumny nie muszą być unikalne. W rzeczywistości możesz uzyskać naprawdę dobrą wydajność z indeksu binarnego podczas wyszukiwania wyjątków.

select * from tblOrder where paidYN='N'
pappes
źródło
Twoja wyraźna wzmianka o kluczach obcych naprawdę wyjaśniła sprawę, biorąc pod uwagę łączenie.
pfabri
3

To naprawdę zależy od twoich zapytań. Na przykład, jeśli piszesz prawie tylko do tabeli, najlepiej nie mieć żadnych indeksów, po prostu spowalniają one zapis i nigdy się nie wykorzystują. Każda kolumna, której używasz do łączenia z inną tabelą, jest dobrym kandydatem na indeks.

Przeczytaj również o funkcji Brakujące indeksy. Monitoruje rzeczywiste zapytania używane w Twojej bazie danych i może powiedzieć, które indeksy poprawiłyby wydajność.

jwanagel
źródło
3

Kolumna GUID nie jest najlepszym kandydatem do indeksowania. Indeksy najlepiej nadają się do kolumn z typem danych, którym można nadać jakąś sensowną kolejność, tj. Posortowane (liczba całkowita, data itp.).

Nie ma znaczenia, czy dane w kolumnie ogólnie rosną. Jeśli utworzysz indeks w kolumnie, indeks utworzy własną strukturę danych, która będzie po prostu odwoływać się do rzeczywistych elementów w tabeli bez obawy o składowane zamówienie (indeks nieklastrowy). Następnie można na przykład przeprowadzić wyszukiwanie binarne w strukturze danych indeksu, aby zapewnić szybkie pobieranie.

Możliwe jest również utworzenie „indeksu klastrowego”, który fizycznie zmieni kolejność danych. Jednak możesz mieć tylko jeden z nich na tabelę, podczas gdy możesz mieć wiele indeksów nieklastrowych.

Popiół
źródło
Cóż, w ten sposób nie jest to do końca dokładne. Możesz łatwo utworzyć zwykły, nieklastrowy indeks w kolumnie GUID - dlaczego nie? GUID ma dużą wadę, jeśli używasz go jako klucza klastrowania (np. Dla CLUSTERED INDEX) - wtedy jest to desaster w użyciu.
marc_s
1

Pierwszą zasadą były kolumny, które są często używane w klauzulach WHERE, ORDER BY i GROUP BY, lub w innych, które wydawały się często używane w łączeniach. Pamiętaj, że mam na myśli indeksy, a nie klucz podstawowy

Nie po to, aby dać „waniliową” odpowiedź, ale tak naprawdę zależy to od tego, w jaki sposób uzyskujesz dostęp do danych

curtisk
źródło
1

Twój klucz podstawowy powinien zawsze być indeksem. (Byłbym zdziwiony, gdyby w rzeczywistości nie był automatycznie indeksowany przez MS SQL.) Powinieneś także indeksować kolumny samodzielnie SELECTlub ORDERczęsto; ich celem jest zarówno szybkie wyszukiwanie pojedynczej wartości, jak i szybsze sortowanie.

Jedynym prawdziwym niebezpieczeństwem związanym z indeksowaniem toowielu kolumn jest spowolnienie zmian w wierszach w dużych tabelach, ponieważ wszystkie indeksy również wymagają aktualizacji. Jeśli naprawdę nie masz pewności, co indeksować, po prostu zmień czas na najwolniejsze zapytania, sprawdź, które kolumny są używane najczęściej i zindeksuj je. Następnie zobacz, o ile są szybsze.

Eevee
źródło
1

Liczbowe typy danych, które są uporządkowane w kolejności rosnącej lub malejącej, są dobrymi indeksami z wielu powodów. Po pierwsze, liczby są generalnie szybsze do oszacowania niż łańcuchy (varchar, char, nvarchar itp.). Po drugie, jeśli wartości nie są uporządkowane, może być konieczne przetasowanie wierszy i / lub stron, aby zaktualizować indeks. To dodatkowe obciążenie.

Jeśli używasz programu SQL Server 2005 i korzystasz z unikatowych identyfikatorów (guidów) i NIE potrzebujesz ich losowego charakteru, sprawdź typ identyfikatora sekwencyjnego.

Wreszcie, jeśli mówisz o indeksach klastrowych, mówisz o rodzaju danych fizycznych. Jeśli masz ciąg jako indeks klastrowy, może to być brzydkie.

Ian Suttle
źródło
0

Powinno być jeszcze szybsze, jeśli używasz identyfikatora GUID. Załóżmy, że masz rekordy

  1. 100
  2. 200
  3. 3000
  4. ....

Jeśli masz indeks (wyszukiwanie binarne, możesz znaleźć fizyczną lokalizację szukanego rekordu w czasie O (lg n), zamiast wyszukiwać sekwencyjnie w czasie O (n). Dzieje się tak, ponieważ nie wiesz, jakie masz rekordy w twoim stole.

Milhous
źródło
0

Najlepszy indeks zależy od zawartości tabeli i tego, co próbujesz osiągnąć.

Zrobiono przykład Baza danych członków z kluczem podstawowym numeru ubezpieczenia społecznego członków. Wybraliśmy SS, ponieważ aplikacja priamry odwołuje się w ten sposób do osoby, ale chcesz również utworzyć funkcję wyszukiwania, która będzie wykorzystywać imię i nazwisko członków. Sugerowałbym wtedy utworzenie indeksu obejmującego te dwa pola.

Najpierw powinieneś dowiedzieć się, jakie dane będziesz odpytywać, a następnie zdecydować, które dane chcesz zindeksować.

Józef
źródło