Ist es eine vorzeitige Optimierung, Datenbankindizes hinzuzufügen?


61

Ein Kollege von mir hat heute vorgeschlagen, dass wir alle Abfragen in unserer Anwendung durchgehen und Indizes entsprechend hinzufügen.

Ich halte dies für eine vorzeitige Optimierung, da unsere Anwendung noch nicht einmal veröffentlicht wurde. Ich schlug vor, nach dem Start auf langsame Abfragen zu achten und dann die Indizes entsprechend hinzuzufügen.

Was ist der allgemeine Konsens beim Entwerfen Ihrer Datenbank? Sollten Sie jedes Mal, wenn Sie eine neue Abfrage schreiben, einen passenden Index hinzufügen? Oder ist es besser, nur zu überwachen und zu sehen, wie es geht?


32
Es könnte eine Ansichtssache sein, jedoch glaube ich, dass einige Indizes von vornherein hinzugefügt werden könnten.
Basile Starynkevitch

2
@BasileStarynkevitch Ich stimme voll und ganz zu, dass wir bereits Primärschlüsselindizes und die Werke haben. Aber wo ziehst du die Grenze?
Marco de Jongh

1
Meine zwei Cent aus Erfahrung: Ich habe einige meiner frühen Suchanfragen in einer Teilmenge unserer Datenbank getestet. Die Tests, die ich durchführte, waren auf meiner lokalen Kopie völlig in Ordnung. Anschließend habe ich die Anwendung in den Staging-Bereich verschoben, in dem sich die vollständige Datenbank befindet. Meine Tests liefen in <500 ms , während die Auflösung des Staging-Systems mehrere Minuten dauerte . Mein Chef war völlig verwirrt, warum die App nicht geladen wurde. Erklären Sie, Operationen sind Ihr Freund ... Suchen Sie zumindest nach sequentiellen Scans auf großen Tabellen!
Chris Cirefice

2
Das Hinzufügen von Indizes ist mit der Verwendung von bubblesort vergleichbar. Meistens werden Sie beim Testen keine Probleme feststellen, aber sobald Ihr Programm im laufenden Betrieb größer wird, werden Sie mit einer ganzen Reihe von Problemen konfrontiert. Und Indizes können den Geschwindigkeitsunterschied leicht um den Faktor 100 verringern.
Pieter B

3
Denken Sie immer daran: Ein Index ist keine magische Sache, die Ihre Abfragen beschleunigt. Ein Index verursacht bei den meisten DML-Operationen Kosten und kann je nach Typ zu viel Wartezeit führen, wenn viele Benutzer dieselbe Tabelle aktualisieren. Für Abfragen: Es gibt viele Abfragen, die von einem Index überhaupt nicht profitieren, bei denen ein FTS am schnellsten ist oder bei denen die Partitionierung die ganze Arbeit für Sie erledigt. - Fügen Sie nur einen Index hinzu, von dem Sie wissen, dass er von Vorteil ist!
Falco

Antworten:


132

Vorzeitige Optimierung "optimiert" etwas aufgrund eines vagen, intuitiven Gefühls, das, wie Sie wissen, wahrscheinlich langsam sein wird, insbesondere zum Nachteil der Lesbarkeit und Wartbarkeit von Code . Dies bedeutet nicht, dass Sie nicht vorsätzlich bewährten Methoden in Bezug auf die Leistung folgen.

Manchmal ist es schwierig, eine Linie zu ziehen, aber ich würde definitiv sagen, dass es zu spät ist, keine Indizes hinzuzufügen, bevor Sie live gehen . Dies bestraft Early Adopters - Ihre eifrigsten und wichtigsten Benutzer - und gibt ihnen eine negative Sicht auf Ihr Produkt, die sie dann in Bewertungen, Diskussionen usw. verbreiten Gute Idee, aber ich würde sicherstellen, dass dies nicht später als in der Beta geschieht.


11
Ja, dies sollte in der Lasttestphase erfolgen
Alvaro,

152
Optimieren, bevor Sie wissen, wo sich die langsamen Teile befinden, ist eine vorzeitige Optimierung. Wenn Sie das Ding freigeben , bevor Sie wissen, wo sich die langsamen Teile befinden, ist dies eine vorzeitige Freigabe !
MathematicalOrchid

4
@MathematicalOrchid: Das ist eine großartige Formulierung! Darf ich es woanders ausleihen?
Pieter Geerkens

3
@PieterGeerkens Klar, hau ab! ;-) Ich bin nur traurig, dass ich mit 91+ Upvotes keine Wiederholung verdiene ... heh.
MathematicalOrchid

3
@ MathematicalOrchid hätte eine Antwort sein sollen. Könnte für die "kleinste-auf den Punkt" Antwort jemals laufen.
Mindwin

48

Überwachen Sie langsame Abfragen, sobald wir online gehen

Denn nichts sagt mehr über Qualität aus, als dass Ihre Benutzer unter Designmangel leiden!

Sie sollten wissen, welche Abfragen Indizes benötigen, wenn Sie die Tabellen entwerfen, und wissen, nach welchen Spalten in where-Klauseln und Joins abgefragt wird. Diese sollten bereits indiziert sein, da sich bei zunehmender Auslastung oder gespeicherten Daten schnell herausstellen kann, was in einer Live-Umgebung möglicherweise nicht erkennbar ist. Was Sie in diesem Fall nicht tun möchten, ist, bei jeder "langsamen" Abfrage auf Indizes zu klicken. Am Ende erhalten Sie einen Index für alles.


10
Richtig. Betrachten Sie Indizes als Teil des Datenbankentwurfs. Verwenden Sie Indizes, um eine vollständige Tabellensuche nach Abfragen zu vermeiden, die der Endbenutzer normalerweise in Echtzeit ausführt.
AE

1
@DocBrown Ich bin mir nicht sicher, ob Sie beim Entwerfen einer Tabelle ein gewisses Verständnis dafür haben (oder haben sollten), wie sie verwendet werden soll. Eine Personentabelle wird anhand der ID oder möglicherweise des Nachnamens abgefragt. Wenn jemand anfängt, über DoB, Adresse oder Telefonnummer zuzugreifen, werden Sie Indizes für jedes Feld hinzufügen - und wo endet das ?!
gbjbaanb

4
@gbjbaanb: Es endet, wenn Benutzer das Hinzufügen von Funktionen zum Produkt einstellen, was je nach Ihrer Methodik "nie" sein kann.
Steve Jessop

1
@SteveJessop Ich meine, Sie indexieren nach den primären Spalten, auf die Sie zugreifen möchten. Für eine Personentabelle haben Sie möglicherweise eine Suchfunktion (wenn Sie Ihren Benutzernamen vergessen, suchen Sie beispielsweise per E-Mail), verwenden anschließend jedoch immer die ID. ID ist also die einzige, die indiziert werden muss. Wenn Sie häufig in anderen Feldern suchen, möchten Sie möglicherweise einen Index. Dies wird mit der Zeit herauskommen. Im Allgemeinen möchten Sie jedoch nicht jede Spalte indizieren, nur weil sich irgendwann jemand dazu entschlossen hat, eine nicht standardmäßige Abfrage zu schreiben Verwenden Sie einen anderen Mechanismus für diese "einmaligen" Fälle.
gbjbaanb

2
@gbjbaanb: Sicher, Leute sollten nicht wiederholt denselben Nachnamen in einer Tabelle nachschlagen, da dies ein geringfügig bequemerer Griff für sie ist als der richtige Schlüssel für die Tabelle. Ich würde sagen, dass dies der Fall ist, unabhängig davon, ob die Tabelle nach dem Nachnamen indiziert ist oder nicht, da ein Codeabschnitt etwas sehr faul ist, das davon ausgeht, dass alles unter "demselben Benutzer" ausgeführt wird, dies jedoch nicht ganz ausdrücken kann im Code, indem ich mich an die ID erinnere :-) Ich stellte mir Fälle vor, in denen die Notwendigkeit eines Reverse-Lookups nicht vorhergesehen wurde, bis der Kunde es erwähnte ...
Steve Jessop

26

"Vorzeitige Optimierung" bedeutet in seinem abfälligen Sinne eine kostenintensive Optimierung, die möglicherweise nicht erforderlich ist. Dies bedeutet nicht, dass alle Optimierungen vor dem letztmöglichen Zeitpunkt durchgeführt wurden, um einen Konkurs zu verhindern!

Insbesondere ist es legitim, basierend auf Leistungstests vor dem Start zu optimieren, um sicherzustellen, dass Sie einige vernünftige (wenn auch ungefähre) Anforderungen erfüllen, damit Ihre App nicht vollständig funktioniert.

Sie sollten Ihre Datenbank mindestens mit einer plausiblen Menge von Testdaten laden und die Reaktionsfähigkeit Ihrer App überprüfen. Dies ist nicht verfrüht, da Sie wissen, dass es passieren wird, und es werden alle Abfragen abgefangen, die absurd langsame Scans auslösen. Wie AE in einem Kommentar sagt:

Verwenden Sie Indizes, um eine vollständige Tabellensuche nach Abfragen zu vermeiden, die der Endbenutzer normalerweise in Echtzeit ausführt

Zumindest für Tabellen, deren Nutzung zunehmen soll.

Wenn Sie über umfangreiche Erfahrungen mit dem Datenbankmodul verfügen und die Tests bereits beim Schreiben des ersten Codeabschnitts geplant haben, werden Sie häufig feststellen, dass Sie die Abfrage ausführen, ohne sie auszuführen Ohne Index ist das Schreiben zu langsam. Natürlich können Sie so tun, als ob Sie es nicht wissen, und beobachten, wie der Test fehlschlägt, bevor Sie den Index zum Bestehen bringen. Es gibt jedoch keinen Grund für den bekannten fehlerhaften Code (da er nicht reagiert), live zu gehen.


20

Ich halte dies für eine vorzeitige Optimierung, da unsere Anwendung noch nicht einmal veröffentlicht wurde. Ich schlug vor, nach dem Start auf langsame Abfragen zu achten und dann die Indizes entsprechend hinzuzufügen.

Sie können Ihre Endbenutzer und Ihre Produktionsumgebung nicht wie eine Qualitätssicherung behandeln. Mit anderen Worten, Sie sagen, Sie werden es in der Produktion herausfinden. Ich denke nicht, dass dies der richtige Weg ist, und ich sehe, dass dieser Ansatz jeden Tag schrecklich schief geht .

Sie müssen eines beachten, da Sie dies nicht mit einem breiten Pinsel malen können.

Was ist Ihre gemeinsame Arbeitsbelastung ?

Das mag offensichtlich oder langweilig klingen, ist aber in der Praxis von Bedeutung. Wenn Sie 10 Abfragen haben, die 98% Ihrer Arbeitslast ausmachen (ziemlich häufig, ob Sie es glauben oder nicht), wäre meine Empfehlung eine harte Analyse vor der Produktion . Stellen Sie mit realistischen und repräsentativen Daten sicher, dass diese 10 Abfragen so gut wie möglich sind ( perfekt ist eine Verschwendung wertvoller Zeit und fast nicht erreichbar).

Bei den anderen 200 Abfragen, die 2% der Arbeitslast ausmachen , handelt es sich wahrscheinlich um Abfragen, die keinen großen Aufwand wert sind und den Eckpfeiler für die Fehlerbehebung bei Unregelmäßigkeiten in der Produktion darstellen. Das ist auch eine Realität und keine schrecklich schlechte Sache. Dies bedeutet jedoch nicht, dass Sie die Best Practices für die Indizierung ignorieren oder geschätzte Annahmen zum Abrufen von Daten treffen.

Es ist gängige und bewährte Methode, die Datenbankleistung vor der Produktion zu ermitteln. Tatsächlich gibt es eine relativ verbreitete Position für diese Art von Dingen, die als Entwicklungs-DBA bezeichnet wird .

Aber...

Einige nehmen das zu weit und machen es wahnsinnig, Indizes "nur für den Fall" hinzuzufügen. Jemand empfiehlt, dass dies ein fehlender Index ist? Fügen Sie es und vier weitere Variationen hinzu. Auch eine schlechte Idee. Sie müssen nicht nur über das Abrufen von Daten nachdenken, sondern auch über die Änderung von Daten. Je mehr Indizes in einer Tabelle vorhanden sind, desto höher ist im Allgemeinen der Overhead beim Ändern von Daten.

Wie die meisten Dinge gibt es ein gesundes Gleichgewicht.

Als lustige kleine Randnotiz ... Die Pluralisierung von "Index"

"Indizes" sind für Finanzleute

"Indizes" sind für uns


2
Das braucht mehr Stimmen. Ich konnte nicht mehr zustimmen.
RubberDuck

+1 für das "nur für den Fall" -Bit (das wäre eine vorzeitige Optimierung). Wenn ich könnte, würde ich wieder für das "Common Workload" -Bit stimmen.
David

Hoffentlich wissen Sie vorher, welche 10 Anfragen zu den 98% gehören und welche nicht.
Paŭlo Ebermann

@ PaŭloEbermann Die meisten DBMS haben die Möglichkeit, diese Informationen schnell und einfach zu erfassen. In diesem Fall gibt es keine Entschuldigung, es nicht zu wissen.
Thomas Stringer

@ThomasStringer Natürlich funktioniert dies nur, wenn Ihre Testfälle vor Produktionsbeginn in irgendeiner Weise damit zusammenhängen, was echte Benutzer in der Produktion tun.
Paŭlo Ebermann

4

Nein, es ist keine vorzeitige Optimierung, aber es muss korrekt durchgeführt werden, wie es bei jeder Optimierung der Fall sein sollte.

Folgendes würde ich tun:

  1. Laden Sie die Datenbank mit genügend Testdaten, um eine Produktionslast nachzuahmen. Sie können dies nicht 100% genau erreichen, aber das ist in Ordnung: Geben Sie einfach genug Daten ein. Enthält eine Tabelle eine feste Datenmenge? Laden Sie es auf. Haben Sie eine Tabelle, die viele Daten enthält, z. B. welche Tabelle auch immer Fragen auf dieser Site enthält? Laden Sie einige Millionen Datensätze, auch wenn es sich nur um Dummy-Daten handelt.
  2. Aktivieren Sie die Profilerstellung auf Ihrem Datenbankserver.
  3. Machen Sie mit einer Kombination aus automatisierten Skripten (bietet Volumen) und echten Benutzern (sie wissen, wie man Dinge kaputt macht) Schluss mit der Anwendung.
  4. Überprüfen Sie die Profildaten. Sind bestimmte Abfragen langsam? Überprüfen Sie die EXPLAIN-Pläne, und prüfen Sie, ob der Datenbankserver angibt, dass ein Index gewünscht wird, dieser jedoch nicht vorhanden ist.

Datenbankserver sind komplexe und intelligente Software. Sie können Ihnen sagen, wie Sie sie optimieren können, wenn Sie zuhören können.

Die Schlüssel sind, die Leistung vor und nach der Optimierung zu messen und sich von der Datenbank mitteilen zu lassen, was sie benötigt .


3

Das Befolgen bewährter Muster für bekannte Probleme (wie das Auffinden eines Datensatzes anhand seiner ID) ist nicht verfrüht. Es ist nur sinnvoll.

Das heißt, Indizes sind nicht immer ein einfaches Geschäft. Während der Entwurfsphase ist es oft schwierig zu wissen, von welchen Indizes Ihr Datenverkehr abhängt und welche Schreiboperationen Engpässe verursachen. Daher würde ich argumentieren, dass einige "offensichtliche" Best Practices für das Schema-Design zum Einsatz kommen (verwenden Sie PKs, die für die entworfenen Lese- / Schreibmuster und Index-FKs geeignet sind). Erstellen Sie jedoch erst dann einen Index, wenn Ihre Stresstests dies erfordern.


Verbringen Sie zusätzliche 30 Sekunden, um etwas zu tun, von dem fast sicher ist, dass es die Leistung verbessert. Es ist sehr unwahrscheinlich, dass es schadet. Dies ist keine vorzeitige Optimierung. Wenn 90% der Operationen in einer Tabelle eine bestimmte Spalte als Schlüssel verwenden, wird entweder deren Indizierung die Leistung verbessern, oder die Leistung wird niemals langsam genug sein, um eine Rolle zu spielen, und das Hinzufügen von Code zum Erstellen des Index kann weniger Zeit in Anspruch nehmen als das Bestimmen, ob dies der Fall ist wirklich notwendig.
Supercat

@supercat "nie" ... Bis Sie Deadlocks in Ihrer Produktionsumgebung sehen ...
Svidgen

Welche realistischen Szenarien stellen Sie sich vor, die mit 90% der Vorgänge, bei denen eine Spalte als Schlüssel verwendet wird, konsistent sind und bei denen das Hinzufügen eines Index zu einem Deadlock führen würde?
Supercat

@supercat Ich bin mir nicht sicher, ob ich deine Suche vollständig verstehe. In Bezug auf eine aktive Anwendung kann fast jede Erhöhung der Ausführungszeit oder der Anzahl der IOS zu Deadlocks führen. ... Das Vorhandensein oder Nichtvorhandensein eines Index in den meisten Anwendungen ist jedoch vernachlässigbar, bis die Datenbank eine kritische Größe und / oder Parallelität erreicht. ZB wenn alle Ihre Indizes nicht mehr in den Speicher passen ...
Svidgen

1
Der Punkt ist, es ist schwierig zu wissen, wie Ihre Abfrage aufgebaut ist, bis typische Anwendungsfälle einem Stresstest unterzogen werden (oder bis Probleme mit unerwartetem Benutzerverhalten in der Produktion auftreten). Wenn Sie eine Seite haben, die sich von tablex.fieldy abhebt, die jedoch nur einmal pro tausend Einfügungen aufgerufen wird ... Der Index kann zu einer Verschlechterung des Nettoergebnisses führen.
Svidgen

2

Wenn Ihre Anwendung freigegeben wird, ist es zu spät.

Zu einem ordnungsgemäßen Entwicklungsprozess sollten jedoch Leistungstests gehören.

Verwenden Sie die Ergebnisse Ihrer Leistungstests, um zu entscheiden, welche Indizes hinzugefügt werden sollen, und überprüfen Sie deren Wirksamkeit, indem Sie die Leistungstests wiederholen.


Wenn eine Anwendung veröffentlicht wird, ist dies ein guter Zeitpunkt, um die Indizes zu optimieren. Schauen Sie sich diese Seite an, stachexchange, Sie können wetten, dass sich die Indizes lange Zeit nach dem Start geändert haben.
LosManos

@ LosManos: Niemand zahlt für die Nutzung von Stack Exchange.
Leichtigkeit Rennen mit Monica

@LightnessRacesinOrbit: Oh nein, Werbetreibende zahlen für die Nutzung von Stack Exchange.

@JonofAllTrades: Es ist ihnen egal, ob wir aufgrund eines fehlenden Index einige Stunden schlechte Performance haben. Mein Punkt ist, dass eine große, kostenlos nutzbare Community-orientierte Website mit einem fortwährenden Distributionszyklus sich stark von einem regelmäßig veröffentlichten, eigenständigen kommerziellen Produkt unterscheidet. Somit ist SE kein gutes Beispiel.
Leichtigkeit Rennen mit Monica

1

Obwohl ich nicht der Meinung bin, dass jede Abfrage optimiert werden sollte, sind Indizes so sehr Teil von RDBMS, dass sie vor der Veröffentlichung berücksichtigt werden müssen. Wenn Sie eine Abfrage ausführen, teilen Sie dem System im Gegensatz zu anderen Formen der Programmierung nicht mit, wie es ausgeführt werden soll. Sie entwickeln eigene Pläne und stützen sich fast immer auf die Verfügbarkeit eines Index. Das Make-up und das Datenvolumen werden zu einem späteren Zeitpunkt ebenfalls berücksichtigt.

Hier sind einige Dinge, die ich berücksichtigen würde:

  1. Es gibt einige Fragen, die Sie in Ihrer frühen Entwicklung identifizieren sollten, von denen Sie nur wissen, dass sie häufig verwendet werden. Konzentriere dich auf sie.
  2. Es wird langsame Abfragen geben. Indizieren Sie diese zuerst, um festzustellen, ob die Leistung immer noch nicht schnell genug ist, und überlegen Sie dann, ob eine Neugestaltung (Denormalisierung kann verfrüht sein) durchgeführt werden soll. Ich mache das lieber vor einer Veröffentlichung. Niemand möchte ein System, bei dem es 10 Minuten dauert, um etwas im Inventar zu finden.
  3. Indizes können die Abfrageleistung verbessern, verhindern jedoch nicht die Datenänderung.
  4. Viele Systeme verfügen über Tools zur Analyse Ihrer Abfragen. Scheuen Sie sich nicht, diese zu verwenden.

Nach Ihrer ersten Überprüfung sollten Sie einige Überlegungen anstellen, wann Sie diese erneut überprüfen sollten und wie Sie in der Lage sein werden, die dazu erforderlichen Informationen zu sammeln (Nutzung überwachen, Kopien von Kundendaten abrufen usw.).

Ich weiß, dass Sie nicht vorzeitig optimieren möchten, aber es ist fast sicher, dass Sie eine schlechte Leistung erzielen, ohne Ihre Datenbank zu indizieren. Wenn Sie dies aus dem Weg räumen, können Sie feststellen, ob andere Bereiche Leistungsprobleme verursachen.


0

Es hängt auch davon ab, wie viele Benutzer Sie erwarten. Sie sollten auf jeden Fall einige Auslastungstests durchführen und sicherstellen, dass Ihre Datenbank mit 10 bis 100 Sekunden und 1000 Sekunden gleichzeitiger Anforderungen Schritt halten kann. Auch hier kommt es darauf an, wie viel Verkehr Sie erwarten und welche Bereiche Sie voraussichtlich stärker als andere nutzen werden.

Im Allgemeinen würde ich die Bereiche fein abstimmen, von denen ich erwarte, dass der Benutzer die meisten Treffer zuerst erzielt. Dann würde ich alles fein abstimmen, das vom Standpunkt der Benutzererfahrung langsam ist. Wann immer Benutzer auf etwas warten müssen, haben sie eine schlechte Erfahrung und werden möglicherweise abgelehnt. Nicht gut!


0

Es ist empfehlenswert, durch eine Vorausanalyse zu ermitteln, welche Spalten definitiv einen Index benötigen. Es besteht die reale Gefahr einer allmählichen oder unerwarteten Verschlechterung der Leistung in der Produktion, wenn die Datenbankgröße zunimmt, wenn Sie absolut keine Indizes haben. Die Situation, die Sie vermeiden möchten, besteht darin, dass für eine häufig ausgeführte Abfrage eine große Anzahl von Tabellenzeilen durchsucht werden muss. Es ist keine vorzeitige Optimierung, Indizes zu kritischen Spalten hinzuzufügen, da Sie über einen Großteil der erforderlichen Informationen verfügen und die potenziellen Leistungsunterschiede erheblich sind (Größenordnungen). Es gibt auch Situationen, in denen der Nutzen von Indizes weniger klar ist oder mehr von den Daten abhängt - Sie können wahrscheinlich die Entscheidung für einige dieser Fälle verschieben.

Einige Fragen, die Sie stellen müssen, sind:

  • Welche Designgrenzen gelten für die Größe der einzelnen Tische?

Wenn Tabellen immer klein sein werden (z. B. <100 Zeilen), ist es keine Katastrophe, wenn die Datenbank die gesamte Tabelle durchsuchen muss. Es kann nützlich sein, einen Index hinzuzufügen, dies erfordert jedoch ein wenig mehr Fachwissen oder Messung.

  • Wie oft wird jede Abfrage ausgeführt und wie lange dauert die Antwort?

Wenn die Abfrage selten ausgeführt wird und keine strengen Anforderungen an die Antwortzeit (z. B. Berichterstellung) gestellt werden und die Anzahl der Zeilen nicht groß ist, ist es wahrscheinlich ziemlich sicher, das Hinzufügen von Indizes aufzuschieben. Auch hier können Fachwissen oder Messungen hilfreich sein, um festzustellen, ob dies von Vorteil ist.

  • Erfordert die Abfrage, dass die Tabelle nicht nur anhand des Primärschlüssels durchsucht wird? ZB Filtern nach Datumsbereich, Verbinden nach einem Fremdschlüssel?

Wenn diese Abfragen häufig ausgeführt werden und Tabellen mit vielen Zeilen berühren, sollten Sie ernsthaft in Betracht ziehen, einen Index vorab hinzuzufügen. Wenn Sie nicht sicher sind, ob dies bei einer Abfrage der Fall ist, können Sie die Datenbank mit einer realistischen Datenmenge füllen und dann den Abfrageplan anzeigen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.