Welche Spalten sind im Allgemeinen gute Indizes?

97

Im Anschluss an " Was sind Indizes und wie kann ich sie verwenden, um Abfragen in meiner Datenbank zu optimieren? ", Wo ich versuche, mehr über Indizes zu erfahren, welche Spalten sind gute Indexkandidaten? Speziell für eine MS SQL Datenbank?

Nach einigem googeln deutet alles, was ich gelesen habe, darauf hin, dass Spalten, die im Allgemeinen zunehmen und eindeutig sind, einen guten Index bilden (Dinge wie MySQLs auto_increment). Ich verstehe das, aber ich verwende MS SQL und ich verwende GUIDs für Primärschlüssel, so scheint es dass Indizes GUID-Spalten nicht zugute kommen würden ...

mmattax
quelle
Wie wäre es mit einem "Kochbuch": mysql.rjweb.org/doc.php/index_cookbook_mysql
Rick James

Antworten:

109

Indizes können eine wichtige Rolle bei der Abfrageoptimierung und der schnellen Suche nach Ergebnissen aus Tabellen spielen. Daher ist es der wichtigste Schritt, auszuwählen, welche Spalten indiziert werden sollen. Es gibt zwei Hauptstellen, an denen wir eine Indizierung in Betracht ziehen können: Spalten, auf die in der WHERE-Klausel verwiesen wird, und Spalten, die in JOIN-Klauseln verwendet werden. Kurz gesagt, solche Spalten sollten indiziert sein, anhand derer Sie bestimmte Datensätze durchsuchen müssen. Angenommen, wir haben eine Tabelle mit dem Namen Käufer, in der die SELECT-Abfrage Indizes wie die folgenden verwendet:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Da im Abschnitt SELECT auf "purchase_id" verwiesen wird, wird MySQL es nicht verwenden, um die ausgewählten Zeilen einzuschränken. Daher besteht keine große Notwendigkeit, es zu indizieren. Das Folgende ist ein weiteres Beispiel, das sich kaum von dem obigen unterscheidet:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Gemäß den obigen Abfragen first_name können last_name-Spalten indiziert werden, da sie sich in der WHERE-Klausel befinden. Ein zusätzliches Feld, country_id aus der Ländertabelle, kann für die Indizierung berücksichtigt werden, da es sich in einer JOIN-Klausel befindet. Daher kann die Indizierung für jedes Feld in der WHERE-Klausel oder einer JOIN-Klausel berücksichtigt werden.

Die folgende Liste enthält auch einige Tipps, die Sie immer beachten sollten, wenn Sie Indizes in Ihre Tabellen erstellen möchten:

  • Indizieren Sie nur die Spalten, die in den Klauseln WHERE und ORDER BY erforderlich sind. Indizierung von Spalten im Überfluss führt zu einigen Nachteilen.
  • Versuchen Sie, die Funktionen "Indexpräfix" oder "Mehrspaltenindex" von MySQL zu nutzen. Wenn Sie einen Index wie INDEX (Vorname, Nachname) erstellen, erstellen Sie keinen INDEX (Vorname). "Indexpräfix" oder "mehrspaltiger Index" wird jedoch nicht in allen Suchfällen empfohlen.
  • Verwenden Sie das NOT NULL-Attribut für die Spalten, in denen Sie die Indizierung berücksichtigen, damit NULL-Werte niemals gespeichert werden.
  • Verwenden Sie die Option --log-long-format, um Abfragen zu protokollieren, die keine Indizes verwenden. Auf diese Weise können Sie diese Protokolldatei untersuchen und Ihre Abfragen entsprechend anpassen.
  • Mit der EXPLAIN-Anweisung können Sie feststellen, wie MySQL eine Abfrage ausführt. Es zeigt, wie und in welcher Reihenfolge Tabellen zusammengefügt werden. Dies kann sehr nützlich sein, um zu bestimmen, wie optimierte Abfragen geschrieben werden und ob die Spalten indiziert werden müssen.

Update (23. Februar 15):

Jeder Index (gut / schlecht) erhöht die Einfüge- und Aktualisierungszeit.

Abhängig von Ihren Indizes (Anzahl der Indizes und Typ) wird das Ergebnis gesucht. Wenn sich Ihre Suchzeit aufgrund des Index erhöht, ist das ein schlechter Index.

Wahrscheinlich in jedem Buch könnte "Indexseite" eine Kapitelstartseite haben, die Themenseitennummer beginnt, auch die Unterthemenseite beginnt. Einige Erläuterungen auf der Indexseite helfen, aber ein detaillierterer Index kann Sie verwirren oder erschrecken. Indizes haben auch Speicher.

Die Indexauswahl sollte sinnvoll sein. Beachten Sie, dass nicht für alle Spalten ein Index erforderlich ist.

Somnath Muluk
quelle
Vielen Dank, Somnath. Bedeutet dies, dass Indizes nur für Spalten erstellt werden sollten, für die wir eine Verwendung planen WHERE, JOINSoder HAVING?
Muhammad Babar
3
Ja, verwenden Sie Indizes für Spalten, in denen Sie WHERE, JOINS oder HAVING verwenden möchten. Beachten Sie jedoch auch, dass für alle Bedingungsspalten keine Indizes erforderlich sind. Manchmal, wenn die Bedingungsspalte nur einmal verwendet wird, ist möglicherweise kein Index erforderlich, während in vielen Abfragen eine andere Bedingungsspalte verwendet wird. Bevorzugen Sie daher mehr für die Indizierung in diese Spalte.
Somnath Muluk
1
Die Antwort würde davon profitieren, "Spalten, auf die in der WHERE-Klausel verwiesen wird, und Spalten, die in JOIN-Klauseln verwendet werden" in einen TL; DR-Abschnitt einzufügen.
jpmc26
Sie sagen also, wenn ich in meiner WHEREKlausel den Wert eines Feldes überprüfe, dessen Spalte nur zwei Werte annehmen kann, sollte ich diese Binärspalte indizieren? Das scheint falsch zu sein.
AjaxLeung
@ AjaxLeung: Erinnere dich an Knuths Maxime "Vorzeitige Optimierung ist die Wurzel allen Übels." Sie können einen Index für Binärspalten erstellen, dies sollte jedoch davon abhängen, zu welchen Kosten (wie Einfügen, Aktualisierungszeiten). Wenn Ihre Geschäftslogik häufig von diesem Binärschalter abhängt, ist möglicherweise eine Binärspalte mit einem Index erforderlich.
Somnath Muluk
20

Einige Leute beantworteten hier eine ähnliche Frage: Woher wissen Sie, was ein guter Index ist?

Grundsätzlich hängt es wirklich davon ab, wie Sie Ihre Daten abfragen. Sie möchten einen Index, der schnell eine kleine Teilmenge Ihres Datasets identifiziert, die für eine Abfrage relevant ist. Wenn Sie niemals nach Datenstempel abfragen, benötigen Sie keinen Index, auch wenn dieser größtenteils eindeutig ist. Wenn Sie nur Ereignisse erhalten, die in einem bestimmten Zeitraum aufgetreten sind, möchten Sie auf jeden Fall eines. In den meisten Fällen ist ein Index zum Geschlecht sinnlos. Wenn Sie jedoch nur Statistiken über alle Männer und separat über alle Frauen erhalten, lohnt es sich möglicherweise, einen zu erstellen. Finden Sie heraus, wie Ihre Abfragemuster aussehen werden, und greifen Sie auf den Parameter zu, der den Suchraum am meisten einschränkt. Dies ist Ihr bester Index.

Berücksichtigen Sie auch die Art des Index, den Sie erstellen - B-Bäume sind für die meisten Dinge gut und erlauben Bereichsabfragen, aber Hash-Indizes bringen Sie direkt zum Punkt (erlauben jedoch keine Bereiche). Andere Arten von Indizes haben andere Vor- und Nachteile.

Viel Glück!

SquareCog
quelle
9

Es hängt alles davon ab, welche Abfragen Sie zu den Tabellen erwarten. Wenn Sie nach allen Zeilen mit einem bestimmten Wert für Spalte X fragen, müssen Sie einen vollständigen Tabellenscan durchführen, wenn ein Index nicht verwendet werden kann.

Indizes sind nützlich, wenn:

  • Die Spalte oder Spalten haben einen hohen Grad an Eindeutigkeit
  • Sie müssen häufig nach einem bestimmten Wert oder Wertebereich für die Spalte suchen.

Sie sind nicht nützlich, wenn:

  • Sie wählen einen großen Prozentsatz (> 10-20%) der Zeilen in der Tabelle aus
  • Die zusätzliche Speicherplatznutzung ist ein Problem
  • Sie möchten die Insert-Leistung maximieren. Jeder Index für eine Tabelle verringert die Einfüge- und Aktualisierungsleistung, da sie jedes Mal aktualisiert werden müssen, wenn sich die Daten ändern.

Primärschlüsselspalten eignen sich normalerweise hervorragend für die Indizierung, da sie eindeutig sind und häufig zum Nachschlagen von Zeilen verwendet werden.

Plasmer
quelle
Bei der Suche nach Zeichenfolgen, bei denen sich der Wert an einer beliebigen Stelle innerhalb der Zeichenfolge befinden kann, wird dieser Index in diesem Fall möglicherweise nicht verwendet.
Arthur Thomas
5

Im Allgemeinen (ich verwende kein mssql und kann daher keine spezifischen Kommentare abgeben) sind Primärschlüssel gute Indizes. Sie sind eindeutig und müssen einen angegebenen Wert haben. (Außerdem machen Primärschlüssel so gute Indizes, dass normalerweise automatisch ein Index erstellt wird.)

Ein Index ist effektiv eine Kopie der Spalte, die sortiert wurde, um eine binäre Suche zu ermöglichen (was viel schneller als eine lineare Suche ist). Datenbanksysteme können verschiedene Tricks verwenden, um die Suche noch weiter zu beschleunigen, insbesondere wenn die Daten komplexer als eine einfache Zahl sind.

Mein Vorschlag wäre, zunächst keine Indizes zu verwenden und Ihre Abfragen zu profilieren. Wenn eine bestimmte Abfrage (z. B. die Suche nach Personen nach Nachnamen) sehr häufig ausgeführt wird, versuchen Sie erneut, einen Index über die relevanten Attribute und das Profil zu erstellen. Behalten Sie den Index bei, wenn Abfragen spürbar beschleunigt und Einfügungen und Aktualisierungen vernachlässigbar verlangsamt werden.

(Entschuldigung, wenn ich Dinge wiederhole, die in Ihrer anderen Frage erwähnt wurden, bin ich vorher nicht darauf gestoßen.)

Zooba
quelle
5

Jede Spalte, die regelmäßig zum Extrahieren von Daten aus der Tabelle verwendet wird, sollte indiziert werden.

Dies beinhaltet: Fremdschlüssel -

select * from tblOrder where status_id=:v_outstanding

beschreibende Felder -

select * from tblCust where Surname like "O'Brian%"

Die Spalten müssen nicht eindeutig sein. Tatsächlich können Sie bei der Suche nach Ausnahmen mit einem Binärindex eine wirklich gute Leistung erzielen.

select * from tblOrder where paidYN='N'
pappes
quelle
Ihre ausdrückliche Erwähnung von Fremdschlüsseln hat die Dinge für mich in Bezug auf Joins wirklich geklärt.
Pfabri
3

Es hängt wirklich von Ihren Fragen ab. Wenn Sie beispielsweise fast nur in eine Tabelle schreiben, ist es am besten, keine Indizes zu haben. Sie verlangsamen nur die Schreibvorgänge und werden nie verwendet. Jede Spalte, die Sie zum Verknüpfen mit einer anderen Tabelle verwenden, ist ein guter Kandidat für einen Index.

Lesen Sie auch die Funktion "Fehlende Indizes". Es überwacht die tatsächlich verwendeten Abfragen für Ihre Datenbank und kann Ihnen sagen, welche Indizes die Leistung verbessert hätten.

jwanagel
quelle
3

Eine GUID-Spalte ist nicht der beste Kandidat für die Indizierung. Indizes eignen sich am besten für Spalten mit einem Datentyp, dem eine sinnvolle Reihenfolge zugewiesen werden kann, dh sortiert (Ganzzahl, Datum usw.).

Es spielt keine Rolle, ob die Daten in einer Spalte im Allgemeinen zunehmen. Wenn Sie einen Index für die Spalte erstellen, erstellt der Index eine eigene Datenstruktur, die einfach auf die tatsächlichen Elemente in Ihrer Tabelle verweist, ohne die gespeicherte Reihenfolge zu berücksichtigen (ein nicht gruppierter Index). Dann kann beispielsweise eine binäre Suche über Ihre Indexdatenstruktur durchgeführt werden, um einen schnellen Abruf zu ermöglichen.

Es ist auch möglich, einen "Clustered-Index" zu erstellen, der Ihre Daten physisch neu anordnet. Sie können jedoch nur einen davon pro Tabelle haben, während Sie mehrere nicht gruppierte Indizes haben können.

Asche
quelle
Nun, das ist auf diese Weise nicht ganz richtig. Sie können problemlos einen regulären, nicht gruppierten Index für eine GUID-Spalte erstellen - warum nicht? Die GUID hat einen großen Nachteil, wenn Sie sie als Clustering-Schlüssel verwenden (z. B. für den CLUSTERED INDEX) - dann ist es eine Katastrophe, sie zu verwenden.
marc_s
1

Die alte Faustregel waren Spalten, die häufig in den Klauseln WHERE, ORDER BY und GROUP BY verwendet werden, oder Spalten, die häufig in Joins verwendet wurden. Denken Sie daran, ich beziehe mich auf Indizes, NICHT auf Primärschlüssel

Keine "vanilleartige" Antwort zu geben, aber es hängt wirklich davon ab, wie Sie auf die Daten zugreifen

Curtisk
quelle
1

Ihr Primärschlüssel sollte immer ein Index sein. (Ich wäre überrascht, wenn es nicht automatisch von MS SQL indiziert würde.) Sie sollten auch Spalten indizieren, die Sie SELECToder ORDERhäufig verwenden. Ihr Zweck ist sowohl die schnelle Suche nach einem einzelnen Wert als auch die schnellere Sortierung.

Die einzige wirkliche Gefahr bei der Indizierung toovieler Spalten besteht darin, Änderungen an Zeilen in großen Tabellen zu verlangsamen, da alle Indizes ebenfalls aktualisiert werden müssen. Wenn Sie sich nicht sicher sind, was Sie indizieren sollen, planen Sie einfach Ihre langsamsten Abfragen, sehen Sie sich an, welche Spalten am häufigsten verwendet werden, und indizieren Sie sie. Dann sehen Sie, wie viel schneller sie sind.

Eevee
quelle
1

Numerische Datentypen, die in aufsteigender oder absteigender Reihenfolge angeordnet sind, sind aus mehreren Gründen gute Indizes. Erstens sind Zahlen im Allgemeinen schneller auszuwerten als Zeichenfolgen (varchar, char, nvarchar usw.). Zweitens, wenn Ihre Werte nicht geordnet sind, müssen möglicherweise Zeilen und / oder Seiten gemischt werden, um Ihren Index zu aktualisieren. Das ist zusätzlicher Aufwand.

Wenn Sie SQL Server 2005 verwenden und die Verwendung von eindeutigen Kennungen (Guids) festlegen und diese NICHT zufällig sein müssen, überprüfen Sie den Typ der sequentiellen eindeutigen Kennungen.

Wenn Sie über Clustered-Indizes sprechen, sprechen Sie schließlich über die Art der physischen Daten. Wenn Sie eine Zeichenfolge als Clustered-Index haben, kann dies hässlich werden.

Ian Suttle
quelle
0

Es sollte noch schneller sein, wenn Sie eine GUID verwenden. Angenommen, Sie haben die Aufzeichnungen

  1. 100
  2. 200
  3. 3000
  4. ....

Wenn Sie einen Index haben (binäre Suche, können Sie den physischen Speicherort des gesuchten Datensatzes in O (lg n) -Zeit finden, anstatt nacheinander in O (n) -Zeit zu suchen. Dies liegt daran, dass Sie nicht wissen, über welche Datensätze Sie verfügen in deinem Tisch.

Milhous
quelle
0

Der beste Index hängt vom Inhalt der Tabelle ab und davon, was Sie erreichen möchten.

Ein Beispiel genommen Eine Mitgliederdatenbank mit einem Primärschlüssel des Mitglieds-Sozialversicherungs-Numnbers. Wir wählen die SS, weil sich die Anwendung priamry auf diese Weise auf die Person bezieht, Sie aber auch eine Suchfunktion erstellen möchten, die den Vor- und Nachnamen der Mitglieder verwendet. Ich würde dann vorschlagen, einen Index über diese beiden Felder zu erstellen.

Sie sollten zuerst herausfinden, welche Daten Sie abfragen werden, und dann bestimmen, welche Daten indiziert werden müssen.

Joseph
quelle