2010-11-24 11 views
13

Das Hinzufügen von Indizes wird hier oft als Abhilfe für Leistungsprobleme vorgeschlagen.Datenbank-Indizes: Eine gute Sache, eine schlechte Sache oder eine Zeitverschwendung?

(Ich spreche über das Lesen & Abfrage nur, wir alle wissen Indizes können Schreiben langsamer machen).

Ich habe dieses Mittel viele Male über viele Jahre sowohl auf DB2 als auch auf MSSQL ausprobiert, und das Ergebnis war immer enttäuschend.

Mein Befund war, dass, egal wie "offensichtlich" es war, dass ein Index die Dinge besser machen würde, es stellte sich heraus, dass der Abfrageoptimierer schlauer war und mein clever ausgewählter Index fast immer schlimmer machte.

Ich sollte darauf hinweisen, dass meine Erfahrungen meist auf kleine Tabellen beziehen (< 100'000 Zeilen).

Kann irgendjemand ein paar nüchterne Richtlinien zu den Optionen für die Indizierung bereitstellen?

Die richtige Antwort wäre eine Liste von Empfehlungen sein etwas wie:

  • Nie/immer Index eine Tabelle mit weniger als/mehr als NNNN Aufzeichnungen
  • Nie immer/Indizes auf Mehrfeld-Tasten betrachten
  • nie/immer Clustered-Indizes
  • verwenden Sie niemals/immer mehr verwenden, als NNN Indizes auf einer einzigen Tabelle
  • nie/immer einen Index hinzufügen, wenn [etwas Magie Zustand zu erfahren über ich sterbe]

Idealerweise wird die Antwort einige aufschlussreiche Beispiele geben.

+0

Es hängt alles von der Geschwindigkeit Ihrer Festplatten und der Größe Ihres Speichers und so weiter ab. – Gabe

+2

Bearbeiten Sie zuerst Ihre Frage! ** Das Hinzufügen von ** Indizes kann eine Abfrage nur schneller, niemals langsamer machen. Was Sie damit zu tun haben, heißt, dass der Abfrageoptimierer ** USE ** einen Index verwendet, der eigentlich die eigenen Befehle außer Kraft setzt ... Das kann die Abfrage verlangsamen –

+3

@Charles Bretana: Hinzufügen eines Index-CAN Eine Abfrage wird langsamer ausgeführt, wenn der Optimierer einen fehlerhaften Plan auswählt oder wenn die Verwendung anderer Indizes beeinträchtigt wird. Das Hinzufügen eines Indexes verlangsamt im Allgemeinen das Einfügen/Aktualisieren/Löschen. – sqlvogel

Antwort

16

Indizes sind wie Chemotherapie ... zu viel und es tötet dich ... zu wenig und du stirbst ... tu es falsch und du stirbst. Du musst wissen, wie viel, wie oft und welche Art, um dich nicht zu töten.

Ihre Hardware, Plattform, Umgebung, laden alle eine Rolle spielen. Also, um Ihre Fragen zu beantworten ..

Ja, möglicherweise manchmal.

+8

Liebe die Chemo-Analogie (Entschuldigung, Charlie Villanueva), aber Sie sollten hinzufügen "egal was passiert, Sie werden sich sehr krank fühlen." – MusiGenesis

+0

@MusiGenesis HAHAHAH !!!! Ja tatsächlich 80))) – Keng

+3

+1 In der Tat, schöne Analogie und wahrscheinlich näher an der Realität als die meisten von uns möchten – smirkingman

2
Always use clustered indexes. 

In der Tat können Sie nicht helfen, aber mit ihnen. Die Daten in einer Tabelle werden sowieso in einer bestimmten Reihenfolge auf der Festplatte angelegt, sie können nicht als Stapel gespeichert werden. Sie haben die Möglichkeit anzugeben, wie genau diese Daten angelegt werden. Warum es verbrennen?

Wenn Sie eine Tabelle haben, in der neue Datensätze angehängt werden und Sie beobachten, dass ein Wert in diesen Datensätzen immer größer wird (z. B. StackOverflow-Fragezahl), erstellen Sie einen Clustered-Index daraus. Dann werden die neuen Daten nicht in der Mitte eingefügt, sondern im Wesentlichen an eine Datei auf der Platte angehängt, was eine relativ billige Operation ist.

2

Grundsätzlich, wenn DB sammelt Daten und es ist lebendig Indizes müssen gehen und entwickeln sich mit diesem Fluss. Es gibt vielleicht einen wirklich guten Index für die Tabelle, aber nachdem ich über XXX Datensätze hinausgegangen bin, ist der gleiche Index in der gleichen Tabelle nutzlos und in diesem Fall sollte er refaktorisiert werden.

Um schnell und DB der einzige Weg ist es die ganze Zeit zu überwachen, wurden optimiert und über die Zeit Refactoring als Datensätze in kommen.

Real life Beispiel ich vor einiger Zeit bekam, war super schnelle Abfrage von einigen eingeschränkt Zeitbereich (created_at zwischen A und B) und super langsame Abfrage, wo der Zeitbereich unterschiedlich war. Gleiche Abfrage, gleiche Datenbank, gleiche Anwendung und nur ein Unterschied im Zeitbereich.

+0

+1 verschiedene Schlüsselbereiche = unterschiedliche Leistung, gut Wie kann man das analysieren/beheben? – smirkingman

0

Scheint, Sie verwechseln zwei Konzepte hier. Hinzufügen von Indizes * allgemein kann nur eine Leseabfrage schneller machen, sehr, sehr selten (fast nie) langsamer. Das Hinzufügen eines Indexes zwingt den Abfrageoptimierer nicht dazu, ihn zu verwenden. Es wird es nur nutzen, wenn es glaubt, dass es davon profitieren kann, und es ist im Allgemeinen sehr klug über diese Entscheidungen.

Für Einfügungen/Aktualisierungen, verletzt natürlich jeder Index Leistung ein bisschen mehr ... Aber am anderen Ende des Spektrums, für, sagen wir, eine Nur-Lese-Datenbank, (wie eine USPS-Adressdatenbank, die monatlich verteilt wird) Im operativen Betrieb gäbe es keine Einfügungen/Aktualisierungen, so dass die einzigen negativen Auswirkungen zusätzlicher Indizes der Speicherplatz ist, den sie belegen.

Das ist ganz unterschiedlich, dass angeben, die der Abfrageoptimierer ein Index verwenden, in der Tat überschreiben, was es auf seine eigenen tun würde ..., die möglicherweise eine Abfrage langsamer machen können.

EDIT: Editiert, um die Möglichkeit für Fehlinterpretation durch übermäßig wörtliche Leser zu beseitigen.

+1

@Charles Bretana: "kann nur eine Abfrage schneller machen, nie langsamer" Ich stimme nicht _vollständig_ überein und das ist genau der Punkt, den ich mache; Das Hinzufügen eines Index ändert die Art und Weise, wie der Abfrageoptimierer seinen Plan erstellt (ein Index wird als starker Hinweis betrachtet). Ich habe die gleiche Abfrage beobachtet (und zeitlich abgestimmt), die erheblich langsamer wird, wenn ein Index hinzugefügt wird. Und bitte unterlasse nicht das, was ich fragen sollte; Die Formulierung der Frage sollte klarstellen, dass ich weiß, wonach ich suche, danke. – smirkingman

+0

@smirkingman, die Randfälle, wo das, was du beschreibst, passiert, sind so selten, dass es sich nicht lohnt, irgendwelche bedeutenden Anstrengungen darauf zu verwenden. Und die Formulierung Ihrer Frage weist darauf hin, dass Sie die Indextechnologie nicht verstehen. "... Index würde die Dinge verbessern, es stellte sich heraus, dass der Abfrageoptimierer schlauer war und mein clever ausgewählter Index fast immer die Dinge verschlimmerte." Diese Staatsmänner können nicht wirklich wahr sein, außer in sehr seltenen und ungewöhnlichen Umständen (es sei denn, Sie überschreiben den Optimierer). Wenn es wahr wäre, würde dies bedeuten, dass der Rest der gesamten Datenbankindustrie nur Idioten sind. –

+1

@Charles Bretana Es tut mir leid, aber sie sind keine Randfälle. _Ihre_Erfahrung könnte sein, dass Indizes immer Dinge besser machen, meins ist es nicht, und es ist genau dieser Mythos, den ich in Frage stelle. Meine Frage ist um so mehr gültig, als ich feststelle, dass die Antworten bisher keine objektive Rechtfertigung haben, mit Ausnahme von Bauchgefühl und/oder Lernen. Oh, und übrigens, ich arbeite seit den frühen 1990ern mit DBMS und habe wahrscheinlich mehr Abende über Abfragepläne verbracht, als du ein warmes Abendessen gehabt hast; Also, anstatt abfällig zu sein, sichern Sie Ihre Antworten mit etwas Konkreterem als dem, was Sie in einem Buch lesen. – smirkingman

10

Als Faustregel gilt, dass Primärschlüssel und Fremdschlüssel indiziert werden müssen. Normalerweise werden Primärschlüssel nur indiziert, indem man sie als solche definiert, aber FKs sind nicht in jeder Datenbank (sie sind definitiv nicht in SQL Server, ich kann nicht wirklich für andere dbs sprechen). Sie werden diese in Joins verwenden, daher ist es im Allgemeinen für die Performance entscheidend, diese zu definieren.

Nun, wenn Sie Felder, die Sie häufig in Verwendung, wo Klauseln, sie von Indizes profitieren können auch mehrere Dinge, die Bereitstellung:

  • Zuerst wird das Feld eine Reihe von Werte haben müssen. Ein Bitfeld oder ein Feld mit nur 2 oder 3 Werte werden fast nie einen Index verwenden.

  • Zweitens müssen die Abfragen, die Sie schreiben, sargable sein. Das heißt, sie müssen so konzipiert sein, dass sie Indizes verwenden. Ich vermute, wenn Sie nie Leistungsverbesserungen von dem, was wie wahrscheinlich Kandidaten für Indizes aussieht, erhalten, dann haben Sie wahrscheinlich Abfragen, die nicht sargable sind. Nehmen Sie zum Beispiel "WHERE Name wie '% Smith'" als Where-Klausel. Ohne die ersten Zeichen zu kennen, kann der Optimierer den Index nicht verwenden.

Kleine Tabellen profitieren nur selten von Indizes. Wenn der Optimierer das Ganze im Speicher halten kann, ist es oft schneller. Wenn Sie mit Multimillion-Record-Tabellen arbeiten würden, würden Sie sehen, dass Indizes von entscheidender Bedeutung sind.

Indexierung kann sehr komplex sein und wenn Sie sich für das Thema interessieren, schlage ich vor, Sie erhalten ein gutes Buch über die Leistung, die Ihre bestimmte Datenbank abstimmt und lesen Sie ausführlich über sie.

+1

+1 für konkrete Vorschläge: Bereich/Sargable/kleine Tabellen – smirkingman

1

Wenn eine Tabelle als Ziel eines Joins erwartet wird, empfiehlt es sich, einen Clustered-Index für diese Tabelle zu verwenden, damit die Joins sequenziell über die Datenseiten ausgeführt werden können. Die Spalten im gruppierten Index werden (in einigen DB-Systemen) in allen anderen Indizes für diese Tabelle enthalten sein, da dies die Werte sind, die die Indizes zum Verweisen auf die Tabellendaten verwenden.Um zu verhindern, dass die anderen Indizes zu groß werden, sollten die Spalten im Clustered-Index so schmal wie möglich sein. Daher empfiehlt es sich, im Clustered-Index nur numerische anstelle von Zeichendaten zu verwenden. Im Allgemeinen sind weniger Spalten besser als mehr Spalten, aber beachten Sie, dass drei int Spalten (12 Byte pro Zeile) viel besser sind als eine Spalte nvarchar(32) (möglicherweise 64 Byte pro Zeile).

Wenn der Clustered-Index eng ist, sollten einige zusätzliche Indizes die Leistung auch bei sehr großen Tabellen nicht stark beeinträchtigen.

2

Sie benötigen Indizes. Nur mit Indizes können Sie schnell auf Daten zugreifen.

Um es so kurz wie möglich zu machen:

  • hinzufügen Indizes für Spalten, die Sie häufig Filterung (oder Gruppierung) für sind. (z. B. ein Zustand oder Name)
  • like und SQL-Funktionen könnte das DBMS keine Indizes verwenden.
  • Indizes nur für Spalten hinzufügen, die viele verschiedene Werte haben (z. B. keine booleschen Felder)
  • Es ist üblich, Indizes zu Fremdschlüsseln hinzuzufügen, aber es wird nicht immer benötigt.
  • Fügen Sie keine Indizes in sehr kurzen Tabellen hinzu
  • Fügen Sie niemals Indizes hinzu, wenn Sie nicht wissen, wie sie die Leistung verbessern sollen.

Endlich: schauen Sie in Ausführungspläne, um zu entscheiden, wie Abfragen optimiert werden.

Sie fügen Indizes nur für eine einzige kritische Abfrage hinzu. In diesem Fall fügen Sie genau die Indizes hinzu, die in der fraglichen Abfrage benötigt werden (mehrspaltige Indizes).

5

Ein Index, der nie verwendet wird, ist eine Verschwendung von Speicherplatz, sowie das Hinzufügen/Aktualisieren/Löschen Zeit. Es ist wahrscheinlich am besten, zuerst den Clustering-Index zu definieren und dann zusätzliche Indizes zu definieren, wenn Sie selbst WHERE-Klauseln schreiben.

Ein häufiger Indexfehler, den ich sehe, ist die Frage, warum eine Auswahl auf Spalte2 (oder Spalte3) so lange dauert, wenn der Index als col1 ASC, col2 ASC, col3 ASC definiert ist. Wenn Sie einen Index mit mehreren Spalten haben, muss Ihre WHERE-Klausel die erste Spalte im Index oder die erste und zweite Spalte im Index usw. verwenden. Wenn Sie auf die Daten mit col2 zugreifen müssen, benötigen Sie einen zusätzlichen Index, der als col2 ASC definiert ist.

Bei Tabellen mit kleinen Domänen ist es manchmal schneller, einen Tabellenscan durchzuführen, als Zeilen mit einem Index aus der Tabelle zu lesen. Dies hängt von der Geschwindigkeit Ihres Datenbanksystems und der Geschwindigkeit des Netzwerks ab.

+0

+1 für die Identifizierung häufiger Fehler und schlägt eine Lösung vor – smirkingman

Verwandte Themen