Najlepsze praktyki postępowania z indeksami baz danych [zamknięte]


17

Jakie są DO i DONT w celu poprawy wydajności bazy danych za pomocą indeksu?

DO byłoby przypadkiem, w którym należy utworzyć indeks lub inną wskazówkę dotyczącą indeksów, która poprawi wydajność.

DONT to przypadek, w którym indeks nie powinien zostać utworzony, lub inna akcja związana z indeksem, która może zaszkodzić wydajności.


3
profil, profil, profil
GrandmasterB

Odpowiedzi:


15

Zależy to częściowo od tego, do czego ma być używana baza danych, ponieważ ogólnie indeksy spowalniają wstawianie i aktualizacje oraz przyspieszają zapytania. W hurtowni danych generalnie nie ma aktualizacji i wstawionych partii, co ułatwia tworzenie indeksów oraz wiele zapytań, które są przyspieszane z dużą ilością indeksów. W internetowej bazie danych sprzedaży internetowej i tym podobnych jest wiele wstawek i aktualizacji, więc posiadanie więcej niż kilku starannie wybranych indeksów spowolni to.

Jeśli otrzymujesz wiele zapytań jednego określonego typu, możesz utworzyć indeks dla zapytania, chociaż jest to więcej w przypadku przetwarzania online niż hurtowni danych. Jeśli niektóre kolumny pojawiają się często w zapytaniach, może być potrzebny indeks w tej kolumnie, a jest to szczególnie przydatne w hurtowniach danych, które są sprawdzane na wiele różnych i często nieprzewidywalnych sposobów.

Za każdym razem, gdy dodajesz lub usuwasz indeks, spróbuj wykonać test wydajności, aby zobaczyć, jaki ma on wpływ. Bez tego strzelasz w ciemno.

Istnieją książki na temat strojenia zapytań i baz danych, często specyficznych dla jednego systemu baz danych i korzystania z narzędzi tego RDBMS. Jeśli jednak musisz dużo zoptymalizować bazę danych, prowadzisz dużą operację i prawdopodobnie powinieneś zatrudnić DBA z odpowiednią wiedzą specjalistyczną.


17

To zależy od tego, jak korzystasz ze swoich stołów. Nie ma jednej i prostej odpowiedzi.

Najlepsza rada, jaką mogę ci dać, to: skorzystaj z usług doradców ds. Tuningu . . Będą analizować polecenia bazy danych podczas korzystania z aplikacji, a następnie przeprowadzą testy obciążenia, aby uzyskać przydatne porady.

Istnieją dla SQL Server i Oracle . Nie wiem, czy mają je inne DBMS, ale wątpię, czy nie zapewniają tak podstawowych narzędzi.

Kilka losowych rekomendacji:

  • Indeksy zapewniają wysoką wydajność przy zastosowaniu do kolumn często zawartych w klauzuli WHERE
  • Użyj indeksu klastrowego dla najczęściej używanych kolumn w zapytaniach.
  • Nie zapominaj, że możesz utworzyć wiele indeksów z kombinacją kolumn (ponieważ są one używane w zapytaniach)
  • Posiadanie wielu indeksów obniży wydajność poleceń INSERT.

Ostatnia rada : jeśli wyniki DB są naprawdę ważne dla twojego projektu, zatrudnij specjalistę. Tak zrobiłem.


2
+1 za indeksy dla kombinacji kolumn. Indeksuje na kolumnach ai nieb jest tym samym co indeks na . Ta ostatnia jest prawie tak dobra, jak indeks przyspieszenia zapytań przy włączonym warunku , jest znacznie lepsza dla zapytań z włączonymi warunkami i , i nie jest przydatna w przypadku samych zapytań . (Większość baz danych z niego nie skorzysta. Oracle zrobi to, ale nie pobiera z tego przebiegu, który regularnie robi.)(a, b)aaabb
btilly

2
+1, dodałby „naucz się czytać plany zapytań, abyś wiedział, co indeksować”
Steven A. Lowe

4

@Pierre 303 już to powiedział, ale powiem to jeszcze raz. NALEŻY używać indeksów dla kombinacji kolumn. Indeks łączony (a, b)jest tylko nieco wolniejszy w przypadku zapytań aniż sam indeks ai jest znacznie lepszy, jeśli zapytanie łączy obie kolumny. Niektóre bazy danych mogą dołączać indeksy przed ai bpo uderzeniu w tabelę, ale nie jest to tak dobre, jak posiadanie połączonego indeksu. Podczas tworzenia indeksu łączonego należy umieścić kolumnę, która najprawdopodobniej zostanie przeszukana jako pierwsza w indeksie łączonym.

Jeśli baza danych obsługuje tę funkcję, DO umieszczaj indeksy na funkcjach wyświetlanych w zapytaniach, a nie w kolumnach. (Jeśli wywołujesz funkcję w kolumnie, indeksy w tej kolumnie są bezużyteczne).

Jeśli używasz bazy danych z prawdziwych tabel tymczasowych, które można tworzyć i niszczyć w locie (np PostgreSQL, MySQL, ale nie Oracle), a następnie NIE tworzyć indeksy na tabelach tymczasowych.

Jeśli używasz bazy danych, która pozwala na to (np Oracle), DO zamek w dobrych planów kwerend. Optymalizatory zapytań z czasem zmienią plany zapytań. Zwykle poprawiają plan. Ale czasami robią to znacznie gorzej. Na ogół tak naprawdę nie zauważysz ulepszeń planu - zapytanie nie było wąskim gardłem. Ale jeden zły plan może zniszczyć ruchliwą witrynę.

NIE mają indeksów na tabelach, na których zamierzasz wykonać duże ładowanie danych. Znacznie, znacznie szybciej jest upuszczać indeksy, ładować dane, a następnie odbudowywać indeksy, niż utrzymywać je podczas ładowania tabeli.

NIE używaj indeksów do zapytań, które mają dostęp do więcej niż niewielkiej części dużej tabeli. (Jak mały zależy od sprzętu. 5% to przyzwoita zasada.) Na przykład, jeśli masz dane z nazwiskami i płcią, nazwiska są dobrym kandydatem do indeksowania, ponieważ dowolna nazwa reprezentuje niewielki ułamek wszystkich wierszy. Indeksowanie według płci nie byłoby pomocne, ponieważ nadal będziesz mieć dostęp do 50% wierszy. Naprawdę chcesz zamiast tego użyć pełnego skanowania tabeli. Powodem jest to, że indeksy kończą losowy dostęp do dużego pliku, co powoduje, że potrzebujesz operacji na dysku. Wyszukiwanie dysku trwa powoli. Na przykład ostatnio udało mi się przyspieszyć godzinne zapytanie, które wyglądało następująco:

SELECT small_table.id, SUM(big_table.some_value)
FROM small_table
  JOIN big_table
    ON big_table.small_table_id = small_table.id
GROUP BY small_table.id

poniżej 3 minut, przepisując go w następujący sposób:

SELECT small_table.id, big_table_summary.summed_value
FROM small_table
  JOIN (
      SELECT small_table_id, SUM(some_value) as summed_value
      FROM big_table
      GROUP BY small_table_id
    ) big_table_summary
    ON big_table_summary.small_table_id =  small_table.id

co zmusiło bazę danych do zrozumienia, że ​​nie powinna próbować używać kuszącego indeksu big_table.small_table_id. (Dobra baza danych, taka jak Oracle, powinna to sobie wyobrazić. To zapytanie działało na MySQL.)

Aktualizacja: Oto wyjaśnienie punktu poszukiwania dysku, który zrobiłem. Indeks umożliwia szybkie sprawdzenie, gdzie znajdują się dane w tabeli. Zwykle jest to wygrana, ponieważ będziesz patrzeć tylko na te dane, na które musisz spojrzeć. Ale nie zawsze, szczególnie jeśli w końcu spojrzysz na wiele danych. Dyski dobrze przesyłają strumieniowo dane, ale spowalniają wyszukiwania. Losowe wyszukiwanie danych na dysku zajmuje 1/200 sekundy. Powolna wersja zapytania zakończyła się zrobieniem około 600 000 z nich i zajęła prawie godzinę. (Przeprowadzono więcej wyszukiwań niż to, ale niektóre z nich przechwyciły buforowanie). Natomiast szybka wersja wiedziała, że ​​musi wszystko przeczytać i przesyłać strumieniowo dane z prędkością około 70 MB / sekundę. Przeszedł przez stół 11 GB w niecałe 3 minuty.


Cześć, jestem zdezorientowany twoim przykładem. Myślałem, że użycie indeksu przyspieszy sprawę, czy nie o to chodzi w indeksach? Czy mówisz, że jeśli zapytanie miałoby dostęp do> 5% tabeli, to indeks indeksu w wyszukiwanej kolumnie spowolniłby sytuację?
Kliknij Upvote

@ Kliknij Upvote: Jeśli zapytanie uzyskuje dostęp do więcej niż 5% (dokładna część wysoce zależna od sprzętu i danych) tabeli, szybciej nie jest używany indeks dla tego zapytania. Posiadanie indeksu nie boli tak długo, jak go nie używasz. Zaktualizuję bardziej szczegółowo, dlaczego tak jest.
btilly

Przydatna informacja. Więcej na ten temat, na przykład mysqlperformanceblog.com/2007/08/28/ ... Zastanawiałem się jednak, czy „ignorowanie klucza” nie jest równoznaczne z tym, że trzeba uczynić z niego podzapytanie?
Inca

@Inca: Nie wiedziałem o „ignoruj ​​klucz”. Przełączam bazy danych na tyle, że często są rzeczy specyficzne dla bazy danych, których nie jestem świadomy. Z dźwięków, które by działały, ale znacznie mniej wydajnie niż moje ostateczne rozwiązanie. Różnica polega na tym, że dołączy, a następnie zgrupuje, podczas gdy moja zgrupuje, a następnie dołączy. Oszczędza to pracy na złączeniu, ponieważ trzeba dołączyć mniej rekordów.
btilly,

„Dobra baza danych (np. Oracle, ale nie MySQL)”: proszę unikać takich głupich materiałów promocyjnych, szczególnie gdy zignorujesz fakt, że MySQL może doskonale używać wielu indeksów w tym samym czasie (zauważono „POŁĄCZENIE INDEKSU” w planach zapytań) .
Patrick Allaert,

2

ZRÓB: Zindeksuj bardzo niewiele pól, do których masz największy dostęp poprzez zapytanie i / lub porównanie.

NIE: Indeksuj wszystkie pola w tabeli, myśląc, że przyspieszy to.

Nie mam żadnych statystyk na ten temat, ale staram się przechowywać nie więcej niż 4 indeksowane pola w tabeli, jeśli mogę pomóc. Normalizacja moich baz danych zwykle pomaga utrzymać te liczby na niskim poziomie, ponieważ wszystko można przeszukiwać za pomocą klawisza numerycznego (który i tak jest szybszy). Staram się trzymać z dala od pełnych pól tekstowych do indeksowania. Są dość ciężkie.


2

Zasadniczo indeksy przyspieszają wyszukiwanie, ale spowalniają pisanie i zajmują miejsce. To jest kompromis.

Każde pole, które jest często używane do dołączania, wyszukiwania / porównywania lub zamawiania według, jest kandydatem do indeksu. Wiedzieć, że to naprawdę szkodliwe, zmierzyć. Jednak klucze obce mocno połączonych tabel z dużą ilością (> 1000) rekordów i kilkoma wstawkami się opłacą.

W przypadku pól tekstowych możesz zaindeksować część pola (na przykład pierwsze 6 znaków), co przyspieszy zapytanie, ale zmniejszy obciążenie indeksów. Wyszukiwanie pełnotekstowe (wyszukiwanie like %substring%) wymaga różnych technik, których nie znam, więc nie mogę ci tam doradzić.

Ważna sytuacja, w której indeksy nie pomogą: nie można użyć indeksu pełnych pól daty i godziny / godziny podczas wyszukiwania (/ przyłączenia / zamówienia) w części daty. Indeks na date_creatednie pomoże ci z zapytaniem takim jak select * from t where year(date_created) = 2011. W mysql nie można utworzyć indeksu po części daty. (Gdy używasz „ between”, a year()nie można użyć indeksu w polu daty).

Więcej informacji na temat MySQL w instrukcji: http://dev.mysql.com/doc/refman/5.6/en/optimization-indexes.html


1

ZRÓB: Staraj się utrzymywać całkowity rozmiar indeksu klastrowego na minimalnym poziomie. Wpisy indeksów klastrowych zostaną uwzględnione w innych indeksach nieklastrowych i stąd może nastąpić marnowanie miejsca na dysku.


1

Pomyśl o tabeli jako o leksykonie, w której artykuły są sortowane według kolejności pojawiania się (lub o braku pomocnej kolejności), a o indeksie tabeli jako indeksie książki do tego leksykonu.

Za pomocą indeksu możesz szybko znaleźć coś w książce. Zamiast skanować całą książkę, musisz tylko znaleźć klucz w indeksie (indeks jest zwykle w jakiś sposób sortowany (według kategorii, dziedziny nauki, epoki historycznej itp.), Co oznacza również, że nie będziesz musiał skanować cały indeks), a następnie przejdź do właściwej strony.

Jednak w przeciwieństwie do książki, stół nie jest raz drukowany, a następnie niezmienny. Jest aktualizowany przez cały czas, dlatego też każdy indeks musi być z nim aktualizowany. Oczywiście wiąże się to z kosztem miejsca i czasu, co można uzasadnić jedynie przydatnością indeksu.

Więc użyj indeksu dla kolumny, jeśli ta kolumna jest używana jako klucz w częstych zapytaniach wyszukiwania, i nie używaj jednego, jeśli nie jest. Słowo „ częste” jest tak dobrym kwantyfikatorem, jak to tylko możliwe, ogólnie mówiąc. Na koniec będziesz musiał dobrze oszacować, które z nich są częste, a następnie po prostu przetestuj wydajność z indeksem lub bez w przypadku wątpliwości.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.