Ich verwende seit einiger Zeit Indizes für meine MySQL-Datenbanken, habe sie jedoch nie richtig kennengelernt . Im Allgemeinen füge ich einen Index für alle Felder hinzu, die ich mithilfe einer WHERE
Klausel suchen oder auswählen werde, aber manchmal scheint es nicht so schwarzweiß zu sein.
Was sind die Best Practices für MySQL-Indizes?
Beispielsituationen / Dilemmata:
Wenn eine Tabelle sechs Spalten enthält und alle durchsuchbar sind, sollte ich alle oder keine indizieren?
Was sind die negativen Performance-Auswirkungen der Indexierung?
Wenn ich eine VARCHAR 2500-Spalte habe, die in Teilen meiner Website durchsucht werden kann, sollte ich sie indizieren?
mysql
indexing
query-optimization
Haroldo
quelle
quelle
Antworten:
Sie sollten auf jeden Fall etwas Zeit damit verbringen, sich mit der Indizierung zu beschäftigen. Es wird viel darüber geschrieben, und es ist wichtig zu verstehen, was los ist.
Im Allgemeinen legt ein Index den Zeilen einer Tabelle eine Reihenfolge auf.
Stellen Sie sich der Einfachheit halber vor, eine Tabelle sei nur eine große CSV-Datei. Immer wenn eine Zeile eingefügt wird, wird sie am Ende eingefügt . Die "natürliche" Reihenfolge der Tabelle ist also nur die Reihenfolge, in der Zeilen eingefügt wurden.
Stellen Sie sich vor, Sie haben diese CSV-Datei in einer sehr rudimentären Tabellenkalkulationsanwendung geladen. In dieser Tabelle werden lediglich die Daten angezeigt und die Zeilen in fortlaufender Reihenfolge nummeriert.
Stellen Sie sich nun vor, Sie müssen alle Zeilen mit dem Wert "M" in der dritten Spalte finden. Je nachdem, was Ihnen zur Verfügung steht, haben Sie nur eine Option. Sie scannen die Tabelle und überprüfen den Wert der dritten Spalte für jede Zeile. Wenn Sie viele Zeilen haben, kann diese Methode (ein "Tabellenscan") lange dauern!
Stellen Sie sich nun vor, Sie haben zusätzlich zu dieser Tabelle einen Index. Dieser bestimmte Index ist der Werteindex in der dritten Spalte. Der Index listet alle Werte aus der dritten Spalte in einer aussagekräftigen Reihenfolge (z. B. alphabetisch) auf und enthält für jeden von ihnen eine Liste der Zeilennummern, in denen dieser Wert angezeigt wird.
Jetzt haben Sie eine gute Strategie, um alle Zeilen zu finden, in denen der Wert der dritten Spalte "M" ist. Zum Beispiel können Sie eine binäre Suche durchführen ! Während beim Tabellenscan N Zeilen gesucht werden müssen (wobei N die Anzahl der Zeilen ist), müssen Sie bei der binären Suche im schlimmsten Fall nur log-n Indexeinträge betrachten. Wow, das ist sicher viel einfacher!
Wenn Sie über diesen Index verfügen und der Tabelle Zeilen hinzufügen (am Ende, da unsere konzeptionelle Tabelle so funktioniert), müssen Sie den Index natürlich jedes Mal aktualisieren. Sie erledigen also etwas mehr Arbeit, während Sie neue Zeilen schreiben, aber Sie sparen eine Menge Zeit, wenn Sie nach etwas suchen.
Im Allgemeinen führt die Indizierung zu einem Kompromiss zwischen Lese- und Schreibeffizienz. Ohne Indizes können Einfügungen sehr schnell sein - das Datenbankmodul fügt der Tabelle nur eine Zeile hinzu. Beim Hinzufügen von Indizes muss die Engine jeden Index aktualisieren, während das Einfügen ausgeführt wird.
Auf der anderen Seite werden Lesevorgänge viel schneller.
Hoffentlich deckt das Ihre ersten beiden Fragen ab (wie andere beantwortet haben - Sie müssen das richtige Gleichgewicht finden).
Ihr drittes Szenario ist etwas komplizierter. Wenn Sie LIKE verwenden, helfen Indizierungs-Engines normalerweise bei Ihrer Lesegeschwindigkeit bis zum ersten "%". Mit anderen Worten, wenn Sie SELECTING WHERE-Spalte wie 'foo% bar%' auswählen, verwendet die Datenbank den Index, um alle Zeilen zu finden, in denen die Spalte mit "foo" beginnt, und muss dann dieses Zwischenzeilenset scannen, um die Teilmenge zu finden das enthält "bar". SELECT ... WHERE Spalte LIKE '% bar%' kann den Index nicht verwenden. Ich hoffe du kannst sehen warum.
Schließlich müssen Sie über Indizes für mehr als eine Spalte nachdenken. Das Konzept ist das gleiche und verhält sich ähnlich wie bei LIKE. Wenn Sie einen Index für (a, b, c) haben, verwendet die Engine den Index weiterhin so gut wie möglich von links nach rechts. Eine Suche in Spalte a könnte also den Index (a, b, c) verwenden, ebenso wie eine in (a, b). Die Engine müsste jedoch einen vollständigen Tabellenscan durchführen, wenn Sie suchen, WO b = 5 UND c = 1)
Hoffentlich hilft dies dabei, ein wenig Licht ins Dunkel zu bringen, aber ich muss wiederholen, dass Sie am besten ein paar Stunden damit verbringen, nach guten Artikeln zu suchen, die diese Dinge ausführlich erklären. Es ist auch eine gute Idee, die Dokumentation Ihres speziellen Datenbankservers zu lesen. Die Art und Weise, wie Indizes von Abfrageplanern implementiert und verwendet werden, kann sehr unterschiedlich sein.
quelle
FULLTEXT
Indizes? Können sie bei Bedingungen wie helfenLIKE '%bar%'
?FULLTEXT
kann bei dieser Abfrage helfen , wennbar
es sich um ein "Wort" handelt.FULLTEXT
behandelt Wörter, nicht beliebige Teilzeichenfolgen (wieLIKE
auch).Schauen Sie sich Präsentationen wie More Mastering the Art of Indexing an .
Update 12/2012: Ich habe eine neue Präsentation von mir veröffentlicht: Wie man Indizes wirklich entwirft . Ich habe dies im Oktober 2012 auf der ZendCon in Santa Clara und im Dezember 2012 auf der Percona Live London vorgestellt.
Das Entwerfen der besten Indizes ist ein Prozess, der mit den Abfragen übereinstimmen muss, die Sie in Ihrer App ausführen.
Es ist schwierig, allgemeine Regeln zu empfehlen, welche Spalten am besten indiziert werden können oder ob Sie alle Spalten indizieren sollten, keine Spalten, welche Indizes mehrere Spalten umfassen sollen usw. Dies hängt von den Abfragen ab, die Sie ausführen müssen.
Ja, es gibt einen gewissen Overhead, sodass Sie keine unnötigen Indizes erstellen sollten. Sie sollten jedoch die Indizes erstellen, die den Abfragen zugute kommen, die Sie für eine schnelle Ausführung benötigen. Der Overhead eines Index wird in der Regel durch seinen Nutzen bei weitem aufgewogen.
Für eine Spalte mit dem Namen VARCHAR (2500) möchten Sie wahrscheinlich einen FULLTEXT-Index oder einen Präfixindex verwenden :
Beachten Sie, dass ein herkömmlicher Index nicht helfen kann, wenn Sie nach Wörtern suchen, die sich möglicherweise in der Mitte dieses langen Varchars befinden. Verwenden Sie dazu einen Volltextindex.
quelle
Ich werde einige der guten Ratschläge in anderen Antworten nicht wiederholen, aber hinzufügen:
Zusammengesetzte Indizes
Sie können zusammengesetzte Indizes erstellen - einen Index, der mehrere Spalten enthält. MySQL kann diese von links nach rechts verwenden . Also, wenn Sie haben:
Wenn Sie einen zusammengesetzten Index haben, der Name / Kategorie / Alter in dieser Reihenfolge enthält, verwenden diese WHERE-Klauseln den Index:
aber
würde diesen Index nicht verwenden, da alles von links nach rechts verwendet werden muss.
Erklären
Verwenden Sie Explain / Explain Extended, um zu verstehen, welche Indizes für MySQL verfügbar sind und welche tatsächlich ausgewählt werden. MySQL verwendet nur EINEN Schlüssel pro Abfrage .
Langsames Abfrageprotokoll
Aktivieren Sie das langsame Abfrageprotokoll, um festzustellen , welche Abfragen langsam ausgeführt werden.
Breite Spalten
Wenn Sie eine breite Spalte haben, in der der größte Teil der Unterscheidung in den ersten mehreren Zeichen erfolgt, können Sie nur die ersten N Zeichen in Ihrem Index verwenden. Beispiel: Wir haben eine ReferenceNumber-Spalte als varchar (255) definiert, aber in 97% der Fälle beträgt die Referenznummer 10 Zeichen oder weniger. Ich habe den Index so geändert, dass nur die ersten 10 Zeichen angezeigt werden, und die Leistung erheblich verbessert.
quelle
Suchen Sie feldweise oder verwenden einige Suchvorgänge mehrere Felder? Auf welchen Feldern wird am häufigsten gesucht? Was sind die Feldtypen? (Index funktioniert beispielsweise bei INTs besser als bei VARCHARs.) Haben Sie versucht, EXPLAIN für die ausgeführten Abfragen zu verwenden?
UPDATEs und INSERTs sind langsamer. Es gibt auch zusätzlichen Speicherplatzbedarf, aber das ist heutzutage normalerweise unwichtig.
Nein, es sei denn, es ist EINZIGARTIG (was bedeutet, dass es bereits indiziert ist) oder Sie suchen nur nach genauen Übereinstimmungen in diesem Feld (ohne die Volltextsuche von LIKE oder mySQL).
Normalerweise indiziere ich die Felder, die am häufigsten abgefragt werden, und dann INTs / BOOLEANs / ENUMs, anstatt Felder, die VARCHARS sind. Vergessen Sie nicht, dass Sie häufig einen Index für kombinierte Felder erstellen müssen, anstatt einen Index für ein einzelnes Feld. Verwenden Sie EXPLAIN und überprüfen Sie das langsame Protokoll.
quelle
Effizientes Laden von Daten : Indizes beschleunigen das Abrufen, verlangsamen jedoch das Einfügen und Löschen sowie das Aktualisieren von Werten in indizierten Spalten. Das heißt, Indizes verlangsamen die meisten Vorgänge, bei denen geschrieben wird. Dies liegt daran, dass für das Schreiben einer Zeile nicht nur die Datenzeile geschrieben werden muss, sondern auch Änderungen an den Indizes. Je mehr Indizes eine Tabelle hat, desto mehr Änderungen müssen vorgenommen werden und desto größer ist die durchschnittliche Leistungsverschlechterung. Die meisten Tabellen erhalten viele Lese- und Schreibvorgänge. Bei einer Tabelle mit einem hohen Prozentsatz an Schreibvorgängen können die Kosten für die Indexaktualisierung jedoch erheblich sein.
Indizes vermeiden : Wenn Sie keinen bestimmten Index benötigen, um die Leistung von Abfragen zu verbessern, erstellen Sie ihn nicht.
Speicherplatz : Ein Index belegt Speicherplatz, und mehrere Indizes belegen entsprechend mehr Speicherplatz. Dies kann dazu führen, dass Sie schneller eine Tabellengrößenbeschränkung erreichen, als wenn keine Indizes vorhanden sind. Vermeiden Sie nach Möglichkeit Indizes.
Takeaway: Nicht über Index
quelle
Im Allgemeinen helfen Indizes dabei, die Datenbanksuche zu beschleunigen, da sie den zusätzlichen Speicherplatz benötigen und
INSERT
/UPDATE
/DELETE
Abfragen verlangsamen . VerwendenEXPLAIN
und lesen Sie die Ergebnisse, um herauszufinden, wann MySQL Ihre Indizes verwendet.Das Indizieren aller sechs Spalten ist nicht immer die beste Vorgehensweise.
(a) Verwenden Sie eine dieser Spalten, wenn Sie nach bestimmten Informationen suchen?
(b) Wie ist die Selektivität dieser Spalten (wie viele unterschiedliche Werte sind dort gespeichert, verglichen mit der Gesamtzahl der Datensätze in der Tabelle)?
MySQL verwendet einen kostenbasierten Optimierer, der versucht, beim Ausführen einer Abfrage den "billigsten" Pfad zu finden. Und Felder mit geringer Selektivität sind keine guten Kandidaten.
Bereits beantwortet: zusätzlicher Speicherplatz, geringere Leistung beim Einfügen - Aktualisieren - Löschen.
Probieren Sie den FULLTEXT-Index aus .
quelle
1/2) Indizes beschleunigen bestimmte Auswahlvorgänge, verlangsamen jedoch andere Vorgänge wie Einfügen, Aktualisieren und Löschen. Es kann eine gute Balance sein.
3) Verwenden Sie einen Volltextindex oder vielleicht eine Sphinx
quelle
slow down other operations like insert, update and deletes
, können SieSTART TRANSACTION;
YOUR CODE HERE;
COMMIT
Folgendes verwenden, umslowing down
die anderen Vorgänge zu vermeiden , da nur eine der Einschränkungen einmal überprüft wird. CAVEAT: Wenn SieREPLACE INTO
und IhreSQL_MODE
<>STRICT_ALL_TABLES
ODERTRADITIONAL
DasBulk Load
ignoriert die ersetzen in und Einsatz von Duplikaten.