Best Practices für Datenbankindizes [geschlossen]


17

Was sind einige DOs und DONTs zur Verbesserung der Datenbankleistung mithilfe von Index?

Ein DO ist ein Fall, in dem ein Index erstellt werden sollte, oder ein anderer indexbezogener Tipp, der die Leistung verbessert.

Ein DONT ist ein Fall, in dem kein Index erstellt werden sollte oder eine andere indexbezogene Aktion, die die Leistung beeinträchtigen kann.


3
Profil, Profil, Profil
GroßmeisterB

Antworten:


15

Dies hängt teilweise davon ab, wofür die Datenbank verwendet werden soll, da Indizes im Allgemeinen Einfügungen und Aktualisierungen verlangsamen und Abfragen beschleunigen. In einem Data Warehouse gibt es in der Regel keine Aktualisierungen und gestapelten Einfügungen, wodurch das Erstellen von Indizes und vielen, vielen Abfragen erleichtert wird, die mit vielen Indizes befüllt werden. In einer Online-Datenbank für Webverkäufe und Ähnliches gibt es viele Einfügungen und Aktualisierungen, sodass mehr als ein paar sorgfältig ausgewählte Indizes die Geschwindigkeit verringern.

Wenn Sie viele Abfragen eines bestimmten Typs erhalten, können Sie einen Index für die Abfrage erstellen, obwohl dies eher für die Online-Verarbeitung als für Data Warehouses gilt. Wenn bestimmte Spalten häufig in Abfragen vorkommen, möchten Sie möglicherweise einen Index für diese Spalte. Dies ist besonders nützlich für Data Warehouses, die auf viele verschiedene und oft unvorhersehbare Arten abgefragt werden.

Versuchen Sie bei jedem Hinzufügen oder Entfernen eines Index, einen Leistungstest durchzuführen, um festzustellen, welche Auswirkungen dies hat. Ohne das schießt du blind.

Es gibt Bücher zum Optimieren von Abfragen und Datenbanken, die häufig nur für ein Datenbanksystem gelten und die Tools dieses RDBMS verwenden. Wenn Sie jedoch feststellen, dass Sie die Datenbank stark optimieren müssen, führen Sie einen großen Vorgang aus und sollten wahrscheinlich einen DBA mit entsprechendem Fachwissen einstellen.


17

Es hängt stark davon ab, wie Sie Ihre Tabellen verwenden. Es gibt keine einfache Antwort.

Der beste Rat, den ich Ihnen geben kann, ist: Verwenden Sie einen Tuning-Berater . Sie analysieren die Datenbankbefehle, während Sie die Anwendung verwenden, und führen anschließend Auslastungstests durch, um Ihnen sinnvolle Hinweise zu geben.

Sie existieren für SQL Server & Oracle . Ich weiß nicht, ob andere DBMS sie haben, aber ich bezweifle, dass sie solche grundlegenden Tools nicht bieten.

Einige zufällige Empfehlungen:

  • Indizes bieten einen hohen Leistungszuwachs, wenn sie auf Spalten angewendet werden, die häufig in der WHERE-Klausel enthalten sind
  • Verwenden Sie den gruppierten Index für die am häufigsten verwendete Spalte in Ihren Abfragen.
  • Vergessen Sie nicht, dass Sie mehrere Indizes mit einer Kombination von Spalten erstellen können (wie sie in Ihren Abfragen verwendet werden).
  • Viele Indizes verringern die Leistung von INSERT-Befehlen.

Letzter Rat : Wenn die DB-Leistung für Ihr Projekt wirklich wichtig ist, sollten Sie einen Spezialisten beauftragen. Das habe ich getan.


2
+1 für Indizes zu Spaltenkombinationen. Indizes für Spalten aund bsind nicht mit einem Index für identisch (a, b). Letzteres ist fast so gut wie der Index afür die Beschleunigung von Abfragen mit einer Bedingung für a, ist massiv besser für Abfragen mit Bedingungen für aund bund ist nicht nur für Abfragen für b. (Die meisten Datenbanken werden es nicht verwenden. Oracle wird es
tun

2
+1, würde hinzufügen "lernen, Abfragepläne zu lesen, damit Sie wissen, was zu indizieren ist"
Steven A. Lowe

4

@ Pierre 303 hat es bereits gesagt, aber ich werde es noch einmal sagen. DO verwenden Indizes für Kombinationen von Spalten. Ein kombinierter Index für (a, b)ist für Abfragen nur geringfügig langsamer aals ein Index für aallein und ist erheblich besser, wenn Ihre Abfrage beide Spalten kombiniert. Einige Datenbanken können Indizes für aund bvor dem Erreichen der Tabelle verknüpfen, dies ist jedoch bei weitem nicht so gut wie ein kombinierter Index. Wenn Sie einen kombinierten Index erstellen, sollten Sie die Spalte, die am wahrscheinlichsten zuerst durchsucht wird, in den kombinierten Index einfügen.

Wenn Ihre Datenbank unterstützt, DO setzen Indizes für Funktionen , die in Abfragen statt Spalten angezeigt. (Wenn Sie eine Funktion für eine Spalte aufrufen, sind die Indizes für diese Spalte unbrauchbar.)

Wenn Sie eine Datenbank mit echten temporären Tabellen verwenden , dass Sie on the fly erstellen und zerstören (zB PostgreSQL, MySQL, aber nicht Oracle), dann DO Indizes für temporäre Tabellen erstellen.

Wenn Sie eine Datenbank verwenden , die es ermöglicht (zB Oracle), DO Sperre in guten Abfrageplänen. Abfrageoptimierer ändern im Laufe der Zeit die Abfragepläne. Sie verbessern normalerweise den Plan. Aber manchmal machen sie es dramatisch schlimmer. Im Allgemeinen werden Sie Planverbesserungen nicht wirklich bemerken - die Abfrage war kein Engpass. Ein einzelner fehlerhafter Plan kann jedoch eine geschäftige Site zum Erliegen bringen.

KEINE Indizes für Tabellen, für die Sie eine große Datenmenge laden möchten. Es ist viel, viel schneller, Indizes zu löschen, die Daten zu laden und anschließend die Indizes neu zu erstellen, als sie beim Laden der Tabelle beizubehalten.

NICHT verwenden Indizes für Abfragen , die mehr als einen kleinen Bruchteil einer großen Tisch Zugriff haben. (Wie klein das ist, hängt von der Hardware ab. 5% sind eine gute Faustregel.) Wenn Sie beispielsweise Daten mit Namen und Geschlecht haben, sind Namen ein guter Kandidat für die Indizierung, da jeder gegebene Name einen kleinen Bruchteil der gesamten Zeilen darstellt. Es wäre nicht hilfreich, nach Geschlecht zu indizieren, da Sie immer noch auf 50% der Zeilen zugreifen müssen. Sie möchten stattdessen wirklich einen vollständigen Tabellenscan verwenden. Der Grund dafür ist, dass Indizes zufällig auf eine große Datei zugreifen, sodass Sie eine Festplattensuche benötigen. Festplatten-Suchvorgänge sind langsam. Als Beispiel habe ich kürzlich eine einstündige Abfrage beschleunigt, die so aussah:

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

auf unter 3 Minuten durch Umschreiben wie folgt:

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

Dies zwang die Datenbank zu verstehen, dass sie nicht versuchen sollte, den verlockenden Index für zu verwenden big_table.small_table_id. (Eine gute Datenbank wie Oracle sollte dies selbst herausfinden. Diese Abfrage wurde unter MySQL ausgeführt.)

Update: Hier ist eine Erklärung des von mir festgelegten Disk-Suchpunkts. Ein Index gibt einen schnellen Überblick darüber, wo sich die Daten in der Tabelle befinden. Dies ist normalerweise ein Gewinn, da Sie nur die Daten anzeigen, die Sie anzeigen müssen. Aber nicht immer, vor allem, wenn Sie sich irgendwann viele Daten ansehen werden. Festplatten streamen Daten gut, machen Suchvorgänge jedoch langsam. Eine zufällige Suche nach Daten auf der Festplatte dauert 1/200 Sekunde. Die langsame Version der Abfrage ergab ungefähr 600.000 Treffer und dauerte fast eine Stunde. (Es wurden mehr Suchvorgänge ausgeführt, aber einige davon wurden durch das Caching erfasst.) Im Gegensatz dazu wusste die schnelle Version, dass sie alles lesen und Daten mit einer Geschwindigkeit von etwa 70 MB / s streamen musste. Es kam durch eine 11 GB-Tabelle in weniger als 3 Minuten.


Hallo, ich bin durch dein Beispiel verwirrt. Ich hätte gedacht, dass die Verwendung des Index die Dinge schneller gemacht hätte, ist das nicht der Sinn von Indizes? Wollen Sie damit sagen, dass ein Index für die Spalte, nach der Sie suchen, langsamer wird, wenn eine Abfrage auf> 5% einer Tabelle zugreift?
Klicken Sie auf "Upvote

@Click Upvote: Wenn eine Abfrage auf mehr als 5% (genauer Anteil, der stark von Hardware und Daten abhängt) einer Tabelle zugreift, ist es schneller, keinen Index für diese Abfrage zu verwenden. Ein Index tut nicht weh, solange Sie ihn nicht verwenden. Ich werde näher darauf eingehen, warum das so ist.
Mittwoch,

Nützliche Informationen. Mehr dazu zum Beispiel mysqlperformanceblog.com/2007/08/28/… Aber ich habe mich gefragt, ob "Schlüssel ignorieren" nicht bis zu diesem Punkt ausreicht, um daraus eine Unterabfrage zu machen?
Inca

@Inca: Mir war nicht bekannt, dass ich den Schlüssel ignoriere. Ich tausche die Datenbanken so oft aus, dass es datenbankspezifische Dinge gibt, die mir nicht bewusst sind. Nach den Geräuschen würde das funktionieren, aber deutlich weniger effizient als meine spätere Lösung. Der Unterschied ist, dass das beitreten würde, dann gruppieren, während meins gruppierte, dann beitrat. Dies spart Arbeit bei der Verknüpfung, da weniger Datensätze verknüpft werden müssen.
Mittwoch,

"Eine gute Datenbank (zB Oracle, aber nicht MySQL)": Bitte vermeiden Sie solche dummen Werbemaßnahmen, insbesondere wenn Sie die Tatsache ignorieren, dass MySQL mehrere Indizes gleichzeitig perfekt verwenden kann (vermerkt in Abfrageplänen "INDEX MERGE"). .
Patrick Allaert

2

DO: Indizieren Sie die wenigen Felder, auf die Sie am häufigsten durch Abfragen und / oder Vergleichen zugreifen.

NICHT: Indizieren Sie jedes Feld in der Tabelle und denken Sie, dass es schneller wird.

Ich habe keine Statistiken dazu, aber ich versuche, nicht mehr als 4 indizierte Felder in einer Tabelle zu halten, wenn ich das ändern kann. Das Normalisieren meiner Datenbanken hilft normalerweise dabei, diese Zahlen niedrig zu halten, da alles über die Zifferntasten durchsucht werden kann (was sowieso schneller ist). Ich versuche, mich für die Indizierung von Volltextfeldern fernzuhalten. Sie sind ziemlich schwer.


2

Grundsätzlich beschleunigen Indizes die Suche, verlangsamen jedoch das Schreiben und belegen Speicherplatz. Das ist der Kompromiss.

Jedes Feld, das häufig zum Beitreten, Suchen / Vergleichen oder Sortieren nach verwendet wird, ist ein Kandidat für einen Index. Zu wissen, dass es wirklich nützlich ist, messen Sie. Die Fremdschlüssel stark verknüpfter Tabellen mit vielen (> 1000) Datensätzen und wenigen Einfügungen zahlen sich jedoch aus.

Bei Textfeldern können Sie einen Teil des Felds indizieren (z. B. die ersten 6 Zeichen), wodurch Ihre Abfrage beschleunigt, die Indizes jedoch entlastet werden. Die Volltextsuche (Suche auf like %substring%) erfordert verschiedene Techniken, mit denen ich nicht vertraut bin, daher kann ich Sie dort nicht beraten.

Eine wichtige Situation, in der Indizes nicht helfen: Sie können den Index der vollständigen Datums- oder Datums- / Uhrzeitfelder nicht verwenden, wenn Sie einen Teil des Datums durchsuchen (/ join / order). Ein Index auf date_createdhilft Ihnen bei einer Abfrage wie nicht select * from t where year(date_created) = 2011. In MySQL können Sie keinen Index für einen Teil des Datums erstellen. (Wenn Sie " between" verwenden, anstatt year()den Index für das Datumsfeld zu verwenden.)

Weitere Informationen zu MYSQL finden Sie im Handbuch: http://dev.mysql.com/doc/refman/5.6/en/optimization-indexes.html


1

DO: Versuchen Sie, die Gesamtgröße des Clustered-Index auf ein Minimum zu beschränken. Die gruppierten Indexeinträge werden in andere nicht gruppierte Indizes aufgenommen, und von hier aus kann Speicherplatz verschwendet werden.


1

Stellen Sie sich eine Tabelle als Lexikon vor, in dem die Artikel nach Erscheinungsbild sortiert sind (oder keine hilfreiche Reihenfolge), und einen Tabellenindex als Buchindex für dieses Lexikon.

Sie verwenden einen Index, um schnell etwas in einem Buch zu finden. Anstatt das ganze Buch zu scannen, müssen Sie nur den Schlüssel im Index finden (ein Index, der normalerweise irgendwie sortiert ist (nach Kategorie, wissenschaftlichem Fachgebiet, historischer Epoche usw.). Dies bedeutet auch, dass Sie nicht scannen müssen den gesamten Index) und dann zur rechten Seite springen.

Im Gegensatz zu einem Buch wird eine Tabelle jedoch nicht einmal gedruckt und ist dann unveränderlich. Es wird ständig aktualisiert, und daher muss jeder Index damit aktualisiert werden. Dies ist natürlich mit einem zeitlichen und räumlichen Aufwand verbunden, der nur durch die Nützlichkeit eines Index gerechtfertigt werden kann.

Verwenden Sie also einen Index für eine Spalte, wenn diese Spalte als Schlüssel für häufige Suchanfragen verwendet wird, und verwenden Sie keinen, wenn dies nicht der Fall ist. Das Wort häufig ist im Allgemeinen ein so guter Quantifizierer wie es nur geht. Am Ende müssen Sie gut einschätzen, welche häufig sind, und dann im Zweifelsfall einfach die Performance mit oder ohne Index messen.

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.