Czy dodawanie indeksów bazy danych jest przedwczesną optymalizacją?

61

Mój kolega dziś zasugerował, abyśmy przejrzeli wszystkie zapytania w naszej aplikacji i odpowiednio dodali indeksy.

Wydaje mi się, że jest to przedwczesna optymalizacja, ponieważ nasza aplikacja nie została jeszcze wydana. Zasugerowałem monitorowanie wolnych zapytań po uruchomieniu, a następnie odpowiednio dodać indeksy.

Jaki jest ogólny konsensus przy projektowaniu bazy danych, czy należy dodawać pasujący indeks za każdym razem, gdy piszesz nowe zapytanie? A może lepiej po prostu monitorować i zobaczyć, jak idzie?

Marco de Jongh
źródło
32
Może to być kwestia opinii, jednak uważam, że niektóre indeksy można dodać z góry.
Basile Starynkevitch
2
@BasileStarynkevitch Całkowicie zgadzam się, że mamy już indeksy kluczy głównych i działa. Ale gdzie narysujesz linię?
Marco de Jongh
1
Moje dwa centy z doświadczenia: testowałem niektóre z moich wcześniejszych zapytań w podzbiorze naszej bazy danych. Testy, które przeprowadziłem, były całkowicie poprawne na mojej lokalnej kopii. Następnie przekazałem aplikację do obszaru przejściowego, w którym znajduje się pełna baza danych. Moje testy przebiegały w <500 ms , a ich rozwiązanie zajęło kilka minut . Mój szef był całkowicie zdezorientowany, dlaczego aplikacja się nie ładuje. Wyjaśnij, że operacje typu są twoim przyjacielem ... Przynajmniej szukaj sekwencyjnych skanów przynajmniej na dużych tabelach!
Chris Cirefice,
2
Brak dodawania indeksów przypomina korzystanie z bąbelków. Najczęściej nie znajdziesz żadnych problemów podczas jego testowania, ale gdy program zacznie się powiększać na żywo, masz wiele problemów. A indeksy mogą łatwo zwiększyć różnicę prędkości o współczynnik 100.
Pieter B,
3
Tylko zawsze pamiętaj: Indeks nie jest magiczną rzeczą, która przyspieszy twoje zapytania. Indeks będzie generował koszty większości operacji DML i w zależności od rodzaju może prowadzić do długiego oczekiwania, gdy wiele osób zaktualizuje ten sam stół. W przypadku zapytań: istnieje wiele zapytań, które w ogóle nie korzystają z indeksu, gdzie FTS jest najszybszy lub gdzie partycjonowanie wykonuje całą pracę za Ciebie. - Dodaj indeks tylko tam, gdzie WIESZ, że będą korzystne!
Falco,

Odpowiedzi:

132

Przedwczesna optymalizacja to „optymalizacja” czegoś z powodu niejasnego, intuicyjnego poczucia, że, wiesz, prawdopodobnie będzie to powolne, szczególnie ze szkodą dla czytelności kodu i możliwości konserwacji . Nie oznacza to umyślnego nieprzestrzegania ugruntowanych dobrych praktyk dotyczących wydajności.

Czasami jest to trudna linia do narysowania, ale zdecydowanie powiedziałbym, że brak dodawania indeksów przed uruchomieniem jest zbyt późną optymalizacją ; będzie to karać początkujących użytkowników - twoich najbardziej chętnych i najważniejszych użytkowników - i da im negatywny pogląd na twój produkt, który będą następnie rozpowszechniane w recenzjach, dyskusjach itp. Monitorowanie zapytań w celu znalezienia problemów wymagających indeksowania to dobry pomysł, ale zrobię to nie później niż w wersji beta.

Mason Wheeler
źródło
11
Tak, należy to zrobić w fazie testowania obciążenia
Alvaro
152
Optymalizacja zanim wiadomo, gdzie znajdują się wolne części, jest przedwczesną optymalizacją. Zwolnienie rzeczy, zanim dowiesz się, gdzie są wolne części, to przedwczesne zwolnienie !
MathematicalOrchid
4
@MathematicalOrchid: To świetne sformułowanie! Czy mogę pożyczyć to gdzie indziej?
Pieter Geerkens,
3
@PieterGeerkens Pewnie, znokautuj! ;-) Jestem po prostu smutny, że ponad 91 głosów pozytywnych nie zarabia mi żadnego rep ... heh.
MathematicalOrchid
3
@MathematicalOrchid powinna być odpowiedzią. Mógłby znaleźć odpowiedź „najmniejszy od razu do rzeczy”.
Mindwin
48

monitoruj wolne zapytania, gdy tylko zaczniemy działać

ponieważ nic nie mówi o jakości, takiej jak powodowanie cierpienia użytkowników z powodu braku projektu!

Powinieneś wiedzieć, które zapytania wymagają indeksów podczas projektowania tabel, wiesz, które kolumny są pytane o to, gdzie klauzule i łączą. Powinny one być już zaindeksowane, ponieważ to, co może nie być widoczne w środowisku na żywo, może szybko ujawnić się, gdy wzrasta obciążenie lub przechowywane dane. To, czego nie chcesz robić, gdy tak się dzieje, to uderzanie indeksów w każde „wolne” zapytanie, a skończysz na indeksie wszystkiego.

gbjbaanb
źródło
10
Dobrze. Rozważ indeksy jako część projektu bazy danych. Użyj indeksów, aby uniknąć pełnego skanowania tabeli dla każdego zapytania, które użytkownik końcowy zwykle wykonuje w czasie rzeczywistym.
AE
1
@DocBrown Nie jestem tego taki pewien, kiedy projektujesz stół, masz (lub powinieneś mieć) trochę wiedzy na temat jego wykorzystania. Tabela osób zostanie zapytana o ID lub ewentualnie nazwisko. Jeśli ktoś zacznie uzyskiwać dostęp przez DoB, adres lub numer telefonu, to dodajesz indeksy dla każdego pola - i gdzie to się kończy ?!
gbjbaanb
4
@gbjbaanb: kończy się, gdy ludzie przestają dodawać funkcje do produktu, co może być „nigdy” w zależności od Twojej metodologii.
Steve Jessop
1
@ SteveJessop Mam na myśli, że indeksujesz według głównych kolumn, do których chcesz uzyskać dostęp. W przypadku tabeli osób możesz mieć funkcję wyszukiwania (jeśli zapomnisz nazwy użytkownika, możesz na przykład wyszukać w wiadomości e-mail), ale później zawsze będziesz używać identyfikatora. Tak więc identyfikator jest jedynym, który wymaga indeksowania. Jeśli często wyszukujesz w innych polach, możesz potrzebować indeksu, pojawi się on na czas, ale generalnie nie chcesz indeksować każdej kolumny tylko dlatego, że ktoś kiedyś postanowił napisać niestandardowe zapytanie, ale możesz zastosować inny mechanizm dla tych „jednorazowych” przypadków.
gbjbaanb
2
@gbjbaanb: jasne, ludzie nie powinni wielokrotnie szukać tego samego nazwiska w tabeli, ponieważ jest to dla nich nieco wygodniejszy uchwyt niż odpowiedni klucz do stołu. Powiedziałbym, że tak jest, niezależnie od tego, czy tabela jest indeksowana według nazwiska, czy nie, ponieważ jest coś bardzo podejrzanego w odcinku kodu, który zakłada, że ​​wszystko działa na „tym samym użytkowniku”, ale nie jest w stanie tego wyrazić w kodzie, zapamiętując identyfikator :-) Wyobrażałem sobie przypadki, w których potrzeba odwrotnego wyszukiwania nie była przewidywana, dopóki klient o tym nie wspomniał ...
Steve Jessop
26

„Przedwczesna optymalizacja” w sensie uwłaczającym oznacza kosztowną optymalizację, która może nie być potrzebna. Nie oznacza to, że cała optymalizacja została wdrożona przed ostatnim możliwym momentem, aby zapobiec bankructwu!

W szczególności uzasadniona jest optymalizacja na podstawie testów wydajności przed uruchomieniem, aby upewnić się, że możesz spełnić pewne rozsądne (aczkolwiek przybliżone) wymagania, aby aplikacja nie była całkowicie do bani.

Przy absolutnym minimum powinieneś załadować bazę danych z wiarygodną ilością danych testowych i sprawdzić reakcję swojej aplikacji. Nie jest to przedwczesne, ponieważ wiesz, że tak się stanie, i będzie przechwytywać zapytania, które wywołują absurdalnie powolne skanowanie. Jak mówi AE w komentarzu:

Użyj indeksów, aby uniknąć pełnego skanowania tabeli dla każdego zapytania, które użytkownik końcowy zwykle wykonuje w czasie rzeczywistym

Przynajmniej dla tabel, które mają rosnąć w użyciu.

W skrócie, jeśli masz duże doświadczenie z silnikiem bazy danych i już zaplanowałeś testy podczas pisania pierwszego wycinka kodu, to często będziesz wiedział, nawet bez uruchamiania, że ​​kwerenda, którą jesteś pisanie będzie zbyt wolne bez indeksu. Oczywiście możesz udawać, że nie wiesz, i oglądać test zakończony niepowodzeniem przed dodaniem indeksu, aby go przejść, ale nie ma powodu, aby znany wadliwy kod (ponieważ nie reagował) został uruchomiony.

Steve Jessop
źródło
20

Wydaje mi się, że jest to przedwczesna optymalizacja, ponieważ nasza aplikacja nie została jeszcze wydana. Zasugerowałem monitorowanie wolnych zapytań po uruchomieniu, a następnie odpowiednio dodać indeksy.

Nie możesz traktować użytkowników końcowych i środowiska produkcyjnego jak zapewniania jakości. Innymi słowy, mówisz, że odkryjesz to w produkcji. Nie sądzę, żeby to była właściwa droga, i widzę, że takie podejście każdego dnia jest strasznie złe .

Musisz pamiętać o jednej rzeczy, ponieważ nie można tego pomalować szerokim pędzlem.

Jakie jest twoje wspólne obciążenie pracą ?

Może to zabrzmieć oczywisto lub nudno, ale w praktyce jest znaczące. Jeśli masz 10 zapytań, które stanowią 98% twojego obciążenia (dość powszechne, wierz lub nie), moja rekomendacja byłaby trudną analizą przed produkcją . Przy realistycznych i reprezentatywnych danych upewnij się, że te 10 zapytań jest tak dobrych, jak to tylko możliwe ( idealne to strata cennego czasu i prawie nieosiągalne).

W przypadku pozostałych 200 zapytań, które stanowią 2% obciążenia , są to te, które najprawdopodobniej nie są warte wiele wysiłku i będą stanowić podstawowe zagadnienie rozwiązywania problemów w produkcji. To także rzeczywistość i wcale nie taka straszna zła rzecz. Ale to nie oznacza ignorowania najlepszych praktyk indeksowania lub dokonywania szacunkowych założeń dotyczących odzyskiwania danych.

Dobrą praktyką jest ustalanie wydajności bazy danych przed produkcją. W rzeczywistości istnieje stosunkowo powszechne stanowisko dla tego typu rzeczy zwanych deweloperskim DBA .

Ale...

Niektórzy posuwają się za daleko i wariują dodając indeksy „na wszelki wypadek”. Ktoś poleca to brakujący indeks? Dodaj go i cztery inne odmiany. Również zły pomysł. Musisz nie tylko pomyśleć o odzyskiwaniu danych, ale co z modyfikacją danych? Im więcej indeksów masz na stole, ogólnie mówiąc, tym więcej masz narzutu podczas modyfikowania danych.

Jak większość rzeczy, istnieje zdrowa równowaga.

Jako zabawna mała uwaga dodatkowa ... Liczba mnoga „Index”

„Wskaźniki” są dla ludzi z branży finansowej

„Indeksy” są dla nas

Thomas Stringer
źródło
2
To wymaga więcej głosów. Nie mogłem się więcej zgodzić.
RubberDuck,
+1 za bit „na wszelki wypadek” ( byłaby to przedwczesna optymalizacja). Gdybym mógł, zagłosowałbym jeszcze raz za bitem „wspólnego obciążenia”.
David
Mam nadzieję, że wiesz wcześniej, które 10 zapytań należy do 98%, a które nie.
Paŭlo Ebermann
@ PaŭloEbermann Większość DBMS ma możliwość szybkiego i łatwego przechwycenia tych informacji. W takim przypadku nie ma usprawiedliwienia dla niewiedzy.
Thomas Stringer
@ThomasStringer Oczywiście działa to tylko wtedy, gdy twoje przypadki testowe przed przejściem do produkcji są w jakiś sposób powiązane z tym, co robią prawdziwi użytkownicy podczas produkcji.
Paŭlo Ebermann
4

Nie, nie jest to przedwczesna optymalizacja, ale musi być wykonana poprawnie tak jak każda optymalizacja.

Oto co bym zrobił:

  1. Załaduj bazę danych wystarczającą ilością danych testowych, aby naśladować obciążenie produkcyjne. Nie możesz uzyskać tej 100% dokładności, ale to jest w porządku: wystarczy wprowadzić wystarczającą ilość danych. Czy jedna tabela ma określoną ilość danych? Załaduj to. Czy masz jedną tabelę, która zawiera wiele danych, np. Dowolna tabela zawiera pytania na tej stronie? Załaduj kilka milionów rekordów, nawet jeśli są to atrapy danych.
  2. Włącz profilowanie na serwerze bazy danych.
  3. Uderz w aplikację za pomocą kombinacji zautomatyzowanych skryptów (zapewnia objętość) i prawdziwych użytkowników (wiedzą, jak to zrobić).
  4. Przejrzyj dane profilowania. Czy określone zapytania są wolne? Sprawdź plany wyjaśniania i sprawdź, czy serwer bazy danych mówi, że chce indeksu, ale nie istnieje.

Serwery baz danych to złożone i inteligentne oprogramowanie. Mogą ci powiedzieć, jak je zoptymalizować, jeśli umiesz słuchać.

Klucze służą do pomiaru wydajności przed i po optymalizacji oraz pozwalają bazie danych powiedzieć, czego potrzebuje .


źródło
3

Postępowanie zgodnie ze sprawdzonymi wzorcami znanych problemów (np. Wyszukiwanie rekordu według jego identyfikatora) nie jest niczym przedwczesnym. To po prostu rozsądne.

To powiedziawszy, indeksy nie zawsze są prostym biznesem. Często trudno jest wiedzieć na etapie projektowania, od których indeksów będzie zależeć ruch, i które będą ograniczały operacje zapisu. Tak więc, argumentowałbym za wykorzystaniem pewnych „oczywistych” najlepszych praktyk w zakresie projektowania schematów (użyj PK odpowiednich dla zaprojektowanych wzorców odczytu / zapisu i indeksów FK); ale nie umieszczaj indeksu na niczym innym, dopóki nie wymagają tego testy warunków skrajnych.

svidgen
źródło
Poświęcenie dodatkowych 30 sekund na zrobienie czegoś, co prawie na pewno poprawi wydajność i bardzo mało prawdopodobne, aby zaszkodziło, nie jest „przedwczesną optymalizacją”. Jeśli 90% operacji na tabeli używa określonej kolumny jako klucza, wówczas albo indeksowanie poprawi wydajność, albo wydajność nigdy nie będzie wystarczająco wolna, aby mieć znaczenie, a dodanie kodu do utworzenia indeksu może zająć mniej czasu niż ustalenie, czy jest to naprawdę konieczne.
supercat
@ superupat „nigdy” ... Dopóki nie zaczniesz widzieć impasu w środowisku produkcyjnym ...
svidgen
Jakie przewidujesz realistyczne scenariusze, które byłyby spójne z 90% operacji wykorzystujących kolumnę jako klucz i gdzie dodanie indeksu spowodowałoby impas?
supercat
@ supercat Nie jestem pewien, czy w pełni rozumiem twoje poszukiwania. Jeśli chodzi o aktywną aplikację, prawie każdy wzrost czasu wykonania lub liczby iOS może spowodować impas. ... Ale przede wszystkim obecność lub brak indeksu w większości aplikacji jest znikoma, dopóki baza danych nie osiągnie krytycznego rozmiaru i / lub poziomu współbieżności. Na przykład, gdy wszystkie twoje indeksy nie mieszczą się już w pamięci ...
svidgen
1
Chodzi o to, że trudno jest określić, jaki jest makijaż zapytania, dopóki typowe przypadki użycia nie zostaną poddane testowi warunków skrajnych (lub dopóki nie wystąpią problemy z nieoczekiwanym zachowaniem użytkownika podczas produkcji). Jeśli masz stronę, która odsuwa się od tablex.fieldy, ale trafia tylko raz na tysiąc wstawień ... Indeks może spowodować degradację sieci.
svidgen
2

Po opublikowaniu aplikacji jest już za późno.

Ale każdy właściwy proces rozwoju powinien obejmować testowanie wydajności.

Skorzystaj z wyników testów wydajności, aby zdecydować, które indeksy dodać, i zweryfikuj ich skuteczność, powtarzając testy wydajności.

Philipp
źródło
Kiedy aplikacja jest wydana, jest to naprawdę dobry moment na ulepszenie wskaźników. Spójrz na tę stronę, stachexchange, możesz się założyć, że wskaźniki zmieniły się długo po uruchomieniu.
LosManos,
@LosManos: Nikt nie płaci za korzystanie z Stack Exchange.
Wyścigi lekkości na orbicie
@LightnessRacesinOrbit: O contraire, reklamodawcy płacą za korzystanie z usługi Exchange Exchange.
@JonofAllTrades: Nie obchodzi ich, czy mamy kilka godzin słabej wydajności z powodu brakującego indeksu. Chodzi mi o to, że duża, bezpłatna, zorientowana na społeczność witryna internetowa z ciągłym cyklem dystrybucji bardzo różni się od okresowo wydawanego, niezależnego produktu komercyjnego. Zatem SE nie jest dobrym przykładem.
Wyścigi lekkości na orbicie
1

Chociaż nie uważam, że każde zapytanie powinno być zoptymalizowane, indeksy są tak bardzo częścią RDBMS, że należy je rozważyć przed wydaniem. Podczas wykonywania zapytania, w przeciwieństwie do innych form programowania, nie mówisz systemowi, jak go wykonać. Opracowują własne plany i prawie zawsze opierają je na dostępności indeksu. Skład i objętość danych będą również brane pod uwagę w późniejszym czasie.

Oto kilka rzeczy, które rozważę:

  1. Jest kilka zapytań, które powinieneś zidentyfikować na wczesnym etapie rozwoju, o których wiesz, że będą często używane. Skoncentruj się na nich.
  2. Będą wolne zapytania. Indeksując je najpierw, możesz następnie ustalić, czy wydajność nadal nie jest wystarczająco szybka, a następnie rozważyć przeprojektowanie (Denormalizacja może być przedwczesna). Wolę to zrobić przed wydaniem. Nikt nie chce systemu, w którym znalezienie czegoś w ekwipunku zajmuje 10 minut.
  3. Indeksy mogą poprawić wydajność zapytań, ale nie utrudniają modyfikacji danych.
  4. Wiele systemów ma narzędzia do analizy zapytań, więc nie bój się ich używać.

Po wstępnej analizie powinieneś wziąć pod uwagę kilka uwag na temat tego, kiedy powinieneś to powtórzyć i jak będziesz w stanie zebrać informacje, aby to zrobić (monitoruj użycie, uzyskaj kopie danych klienta itp.).

Zdaję sobie sprawę, że nie chcesz przedwcześnie optymalizować, ale jest prawie pewne, że będziesz mieć niską wydajność bez indeksowania bazy danych. Usuwając to z drogi, możesz ustalić, czy istnieją inne obszary powodujące problemy z wydajnością.

JeffO
źródło
0

Zależy to również od liczby oczekiwanych użytkowników. Zdecydowanie powinieneś wykonać test obciążenia i upewnić się, że Twoja baza danych jest w stanie nadążyć za jednoczesnym żądaniem od 10 do 100 do 1000. Znowu zależy to od oczekiwanego natężenia ruchu i obszarów, które mają być używane częściej niż inne.

Ogólnie rzecz biorąc, precyzyjnie dostroiłbym obszary, które według mnie będą najbardziej trafiać jako pierwsze. Następnie dostroiłbym wszystko, co jest wolne z punktu widzenia doświadczenia użytkownika. Ilekroć użytkownik musi na coś poczekać, ma złe doświadczenia i może zostać odrzucony. Niedobrze!

harsimranb
źródło
0

Dobrą praktyką jest ustalenie, które kolumny zdecydowanie potrzebują indeksu na podstawie niektórych wstępnych analiz. Istnieje realne ryzyko stopniowego lub nieoczekiwanego obniżenia wydajności produkcji, ponieważ rozmiar bazy danych rośnie, jeśli nie masz absolutnie żadnych indeksów. Sytuacja, której chcesz uniknąć, polega na tym, że często uruchamiane zapytanie wymaga skanowania dużej liczby wierszy tabeli. Optymalizacja nie jest przedwczesnym dodawaniem indeksów do krytycznych kolumn, ponieważ masz wiele niezbędnych informacji, a potencjalne różnice w wydajności są znaczące (rzędy wielkości). Istnieją również sytuacje, w których korzyści wynikające z indeksów są mniej wyraźne lub bardziej zależne od danych - prawdopodobnie możesz odroczyć podjęcie decyzji w niektórych z tych przypadków.

Niektóre pytania, które musisz zadać, to:

  • Jakie będą granice projektu dla wielkości każdego stołu?

Jeśli tabele zawsze będą małe (powiedzmy <100 wierszy), nie jest katastrofą, jeśli baza danych musi przeskanować całą tabelę. Dodanie indeksu może być korzystne, ale wymaga to nieco więcej wiedzy lub pomiaru.

  • Jak często będzie uruchamiane każde zapytanie i jaki jest wymagany czas odpowiedzi?

Jeśli zapytanie jest uruchamiane rzadko i nie ma ścisłych wymagań dotyczących czasu odpowiedzi (np. Generowanie raportu), a liczba wierszy nie jest duża, prawdopodobnie odroczenie dodawania indeksów jest dość bezpieczne. Znów wiedza specjalistyczna lub pomiar może pomóc stwierdzić, czy będzie to korzystne.

  • Czy zapytanie wymaga przeszukania tabeli poza czymś innym niż klucz podstawowy? Np. Filtrowanie według zakresu dat, dołączanie do klucza obcego?

Jeśli te zapytania są uruchamiane często i dotykają tabel z wieloma wierszami, powinieneś poważnie rozważyć zapobiegawcze dodanie indeksu. Jeśli nie masz pewności, czy tak jest w przypadku zapytania, możesz zapełnić bazę danych realistyczną ilością danych, a następnie spójrz na plan zapytań.

użytkownik611910
źródło