2009-06-26 14 views
42

W ActiveRecord Istnieją dwa sposoby, aby zadeklarować indeksów dla wielu kolumn:Indeks dla wielu kolumn w ActiveRecord

add_index :classifications, [:species, :family, :trivial_names]
add_index :classifications, :species 
add_index :classifications, :family 
add_index :classifications, :trivial_names

Czy jest jakaś różnica między pierwszym podejściu i drugim? Jeśli tak, to kiedy powinienem użyć pierwszego i drugiego?

+0

Dziękuję, Collimarco, za wybranie mojej odpowiedzi jako "odpowiedź". –

Odpowiedz

84

Porównywasz indeks złożony z zestawem niezależnych indeksów. Są po prostu inne.

Pomyśl o tym w następujący sposób: indeks złożony umożliwia szybkie sprawdzenie pierwszego pola w zagnieżdżonym zbiorze pól, a następnie szybkie sprawdzenie drugiego pola w obrębie TYLKO rekordów już wybranych przez pierwsze pole, a następnie szybkie wyszukiwanie trzeciego pola - ponownie tylko w rekordach wybranych przez poprzednie dwa indeksy.

Pozwala wziąć przykład. Twój aparat bazy danych zajmie nie więcej niż 20 kroków, aby zlokalizować unikalną wartość w obrębie 1 000 000 rekordów (jeśli pamięć obsługuje) , jeśli używasz indeksu jako. Jest to prawdą, niezależnie od tego, czy korzystasz z indeksu złożonego, czy niezależnego - ale TYLKO dla pierwszego pola ("gatunek" w twoim przykładzie, chociaż myślę, że chcesz rodziny, gatunków, a następnie nazwy zwykłej).

Teraz załóżmy, że istnieje 100 000 pasujących rekordów dla tej pierwszej wartości pola. Jeśli masz tylko pojedyncze indeksy, wówczas każde wyszukiwanie w tych rekordach zajmie 100 000 kroków: po jednym dla każdego rekordu pobranego przez pierwszy indeks. Wynika to z faktu, że drugi indeks nie będzie używany (w większości baz danych - jest to trochę uproszczone) i należy użyć dopasowania brute force.

Jeśli masz Composite Index to wyszukiwanie jest znacznie szybsze, ponieważ drugi wyszukiwania pole będzie mieć indeks ciągu pierwszy zbiór wartości. W tym przypadku nie potrzebujesz więcej niż 17 kroków, aby uzyskać pierwszą pasującą wartość na polu 2 w obrębie 100 000 wyników w polu 1 (baza logów 2 na 100 000).

A więc: kroki potrzebne do znalezienia unikalnego rekordu z bazy danych o wartości 1 000 000 rekordów przy użyciu złożonego indeksu na 3 zagnieżdżonych polach, z których pierwszy pobiera 100 000, a drugi pobiera 10 000 = 20 + 17 + 14 = 51 kroków.

Kroki potrzebne w tych samych warunkach przy samych niezależnych wskaźnikach = 20 + 100 000 + 10 000 = 110,020 kroków.

Duża różnica, co?

Teraz nie iść orzechy wprowadzenie indeksy kompozytowe wszędzie. Po pierwsze, są drogie na wstawkach i aktualizacjach. Po drugie, można je wykorzystać tylko wtedy, gdy rzeczywiście przeszukujesz dane zagnieżdżone (w innym przykładzie używam ich podczas pobierania danych do logowania dla klienta w określonym zakresie dat). Ponadto nie są tego warte, jeśli pracujesz ze stosunkowo małymi zestawami danych.

Na koniec sprawdź dokumentację bazy danych. Bazy danych stały się niezwykle wyrafinowane w zakresie możliwości wdrażania indeksów w tych dniach i scenariusz bazy danych 101, który opisałem powyżej, może nie mieć miejsca dla niektórych (chociaż zawsze rozwijam się tak, jak gdyby tak, tylko wiem, co otrzymuję).

+0

Dzięki za wyjaśnienie! Zobacz, o co prosiłem pana Matta: klauzula WHERE zawiera OR. Czy w takim przypadku przydatny jest indeks złożony? Powiedziałbym, że nie, ponieważ db zawsze musi przeszukiwać wszystkie pozycje, a nie tylko wiersze, które wynikają z pierwszego warunku (inaczej by było, gdyby był operator AND, ponieważ "filtruje" wiersze i zmniejsza zakres) . Czy się mylę? – collimarco

+3

collimarco - w przykładzie podanym dla Pana Matta niezależne wskaźniki zapewniłyby lepszą wydajność, ponieważ każdy z nich byłby wykorzystywany niezależnie jako część planu wykonania SQL. Pomyśl o tym w ten sposób: AND jest kompozycyjny, OR jest niezależny. Aby podać inny przykład, jeśli twoja klauzula where brzmiała: "WHERE (Family = X AND Gatunek = Y) OR (CommonName = Z)", to potrzebujesz złożonego indeksu na Family | Gatunek i niezależnego indeksu na CommonName. –

+0

BTW: Plany SQL Execution są dostępne w bardziej zaawansowanych bazach danych, takich jak SQL Server i Oracle i mogą być dość cenne zarówno jako narzędzie dydaktyczne (aby pomóc Ci zobaczyć, co dzieje się pod kołdrą jako próba bazy danych do optymalizacji planu wyszukiwania) i jako mechanizm testowania różnych strategii indeksowania. –

1

From the docs:

Tworząc indeks stwardnienie kolumn, pierwsza kolumna jest używana jako nazwy indeksu. Na przykład, gdy poda się indeks w dwóch kolumnach [: first,: last], DBMS utworzy indeks dla obu kolumn oraz indeks dla pierwszej kolumny: pierwsza. Używanie tylko imienia dla tego indeksu ma sens, ponieważ nie będziesz musiał tworzyć pojedynczego indeksu o tej nazwie.

Pierwsza metoda służy do tworzenia indeksu złożonego, a druga do tworzenia indeksów pojedynczych atrybutów.

Istnieje kilka dobrych punktów here on when to use compound indexes, ale istotą jest to, że są dobre, gdy wykorzystują miejsce na wielu atrybutach. Zauważ, że powinny być używane razem z innymi indeksami (zawsze indeksuj klucze foriegn) - nie jako zamiennik.

+0

Dzięki! Ale ... kiedy ma sens stosowanie indeksu złożonego zamiast indeksu na jednym atrybucie? Czy możesz podać mi jakieś przykłady? – collimarco

+0

Zaktualizowałem moją odpowiedź – Codebeef

+0

Powiedziałeś, że nie użyję ich jako zamiennika, ale co, jeśli użyję ich tylko w tym zapytaniu: WYBIERZ * Z klasyfikacji WHERE gatunki LIKE '% sth%' LUB rodzina LIKE '% sth%' OR trivial_names LIKE "% sth%" Czy w takim przypadku należy stosować tylko indeks złożony? – collimarco

10

Te dwa podejścia są różne. Pierwszy tworzy pojedynczy indeks na trzech atrybutach, drugi tworzy trzy indeksy o jednym atrybucie. Wymagania dotyczące pamięci będą różne, chociaż bez dystrybucji nie można powiedzieć, która z nich byłaby większa.

Indeksowanie trzech kolumn [A, B, C] działa dobrze, gdy trzeba uzyskać dostęp do wartości A, A + B i A + B + C. Nie będzie dobrze, jeśli twoje zapytanie (lub warunki wyszukiwania itp.) Nie będą się odwoływać do A.

Gdy A, B i C są indeksowane oddzielnie, niektóre optymalizatory zapytań DBMS rozważą połączenie dwóch lub więcej indeksów (temat do estymatora wydajności optymalizatora), aby dać podobny wynik do pojedynczego indeksu z wieloma kolumnami.

Załóżmy, że masz jakiś system e-commerce. Chcesz zapytać o zamówienia według daty zakupu, klienta i czasami obu. Zacznę od stworzenia dwóch indeksów: po jednym dla każdego atrybutu.

Z drugiej strony, jeśli zawsze wybierzesz date_kodowania i customer_id, to jeden indeks w obu kolumnach będzie prawdopodobnie najbardziej wydajny. Kolejność jest znacząca: jeśli chcesz również zapytać o zamówienia dla wszystkich dat dla klienta, ustaw parametr customer_id jako pierwszą kolumnę w indeksie.