Zwei einspaltige Indizes gegen einen zweispaltigen Index in MySQL?

113

Ich bin mit folgenden Problemen konfrontiert und bin mir nicht sicher, was die beste Vorgehensweise ist.

Betrachten Sie die folgende Tabelle (die groß wird):

id PK | giver_id FK | Empfänger_ID FK | Datum

Ich verwende InnoDB und nach meinem Verständnis werden automatisch Indizes für die beiden Fremdschlüsselspalten erstellt. Ich werde jedoch auch viele Abfragen durchführen, bei denen ich eine bestimmte Kombination von:

SELECT...WHERE giver_id = x AND recipient_id = t.

Jede solche Kombination ist in der Tabelle eindeutig.

Gibt es einen Vorteil beim Hinzufügen eines zweispaltigen Index über diese Spalten, oder wären die beiden einzelnen Indizes theoretisch ausreichend / gleich?

Tom
quelle
1
Wenn die Kombination der beiden Spalten eindeutig ist, können Sie einen zweispaltigen Index mit einer eindeutigen Funktion erstellen, der nicht nur die Geschwindigkeit Ihrer Abfrage erhöht, sondern auch die Konsistenz Ihrer Tabelle erhöht.
sguven
"MySQL kann mehrspaltige Indizes für Abfragen verwenden, die alle Spalten im Index testen, oder für Abfragen, die nur die erste Spalte, die ersten beiden Spalten, die ersten drei Spalten usw. testen. Wenn Sie die Spalten rechts angeben In der Indexdefinition kann ein einzelner zusammengesetzter Index mehrere Arten von Abfragen in derselben Tabelle beschleunigen. " -
Mehrspaltige
Auf @ user1585784 extrapolieren; Wenn die Kombination der beiden Spalten eindeutig ist, sollte man meiner Meinung nach einen eindeutigen Schlüssel für sie verwenden. In der Tat, wenn man die Eindeutigkeit auf Datenbankebene erzwingen will, ist ein eindeutiger Schlüssel der einfachste Weg ...
Erk

Antworten:

132

Wenn Sie zwei einspaltige Indizes haben, wird in Ihrem Beispiel nur einer davon verwendet.

Wenn Sie einen Index mit zwei Spalten haben, ist die Abfrage möglicherweise schneller (Sie sollten messen). Ein zweispaltiger Index kann auch als einspaltiger Index verwendet werden, jedoch nur für die zuerst aufgeführte Spalte.

Manchmal kann es nützlich sein, einen Index für (A, B) und einen anderen Index für (B) zu haben. Dies macht Abfragen mit einer oder beiden Spalten schnell, verbraucht aber natürlich auch mehr Speicherplatz.

Bei der Auswahl der Indizes müssen Sie auch die Auswirkungen auf das Einfügen, Löschen und Aktualisieren berücksichtigen. Mehr Indizes = langsamere Updates.

Mark Byers
quelle
1
"MySQL kann mehrspaltige Indizes für Abfragen verwenden, die alle Spalten im Index testen, oder für Abfragen, die nur die erste Spalte, die ersten beiden Spalten, die ersten drei Spalten usw. testen. Wenn Sie die Spalten rechts angeben In der Indexdefinition kann ein einzelner zusammengesetzter Index mehrere Arten von Abfragen in derselben Tabelle beschleunigen. " -
Mehrspaltige
33

Ein Deckungsindex wie:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

... würde bedeuten, dass der Index verwendet werden könnte, wenn auf eine Abfrage verwiesen giver_idwird oder eine Kombination aus giver_idund recipient_id. Beachten Sie, dass die Indexkriterien ganz links basieren - eine Abfrage, auf die nur recipient_idverwiesen wird, kann den Deckungsindex in der von mir angegebenen Anweisung nicht verwenden.

Darüber hinaus kann MySQL nur einen Index pro SELECT verwenden, sodass ein abdeckender Index das beste Mittel zur Optimierung Ihrer Abfragen ist.

OMG Ponys
quelle
9
MySQL can only use one index per SELECTDies ist nicht mehr wahr. Es wäre schön, wenn Sie Ihre Antwort so bearbeiten würden, dass sie aktualisiert wird.
Davor
Würde es Ihnen etwas ausmachen zu erklären, warum der Deckungsindex nicht von verwendet werden kann recipient_id?
Ivo Pereira
2
@IvoPereira Mit mehrspaltigen Indizes in MySQL können Sie alle Felder im Index von links nach rechts verwenden. Wenn Sie beispielsweise eine haben, INDEX (col1, col2, col3, col4)wird der Index für Suchvorgänge mit einer WHEREKlausel wie col1 = 'A'oder col1 = 'A' AND col2 = 'B'oder angewendet col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D', aber dieser bestimmte Index wird für nichts wie WHERE col2 = 'B'oder verwendet, WHERE col3 = 'C' AND col4 = 'D'da die Suchfelder in der Indexdefinition nicht am häufigsten belassen werden. Sie müssten zusätzliche Indizes hinzufügen, um diese Felder abzudecken.
Slicktrick
"ein Index pro SELECT" , gilt dies immer noch für Mariadb 10.1?
Oldboy
1
@Anthony: Nein. Siehe den Kommentar von Davor oben.
Kapad
4

Wenn einer der Fremdschlüsselindizes bereits sehr selektiv ist, sollte das Datenbankmodul diesen für die von Ihnen angegebene Abfrage verwenden. Die meisten Datenbankmodule verwenden eine Art Heuristik, um in dieser Situation den optimalen Index auswählen zu können. Wenn keiner der Indizes für sich genommen sehr selektiv ist, ist es wahrscheinlich sinnvoll, den auf beiden Schlüsseln basierenden Index hinzuzufügen, da Sie sagen, dass Sie diese Art von Abfrage häufig verwenden werden.

Eine andere Sache zu prüfen ist , ob Sie die PK - Feld in dieser Tabelle beseitigen und den Primärschlüssel Index für die definieren giver_idund recipient_idFelder. Sie sagten, dass die Kombination einzigartig ist, so dass dies möglicherweise funktionieren würde (unter vielen anderen Bedingungen, die nur Sie beantworten können). Normalerweise denke ich jedoch, dass die zusätzliche Komplexität, die hinzugefügt wird, den Aufwand nicht wert ist.

Mark Wilkins
quelle
Danke Mark, einer der Schlüssel ist in der Tat sehr selektiv, also sollte es in Ordnung sein. Ich habe mich dafür entschieden, die beiden (automatischen) Indizes beizubehalten und zu sehen, wie sie sich im Laufe der Zeit entwickeln. Ich dachte auch über einen kombinierten Geber: Empfänger-Primärschlüssel nach, aber da jedes Feld auch einzeln durchsuchbar sein muss, würde dies nur den PHP-Overhead erhöhen. Außerdem wäre der neue Schlüssel eine (längere) Zeichenfolge anstelle einer (kürzeren) Ganzzahl.
Tom
2

Eine weitere zu berücksichtigende Sache ist, dass die Leistungsmerkmale beider Ansätze auf der Größe und Kardinalität des Datensatzes basieren. Möglicherweise stellen Sie fest, dass der 2-Spalten-Index erst bei einem bestimmten Schwellenwert für die Datensatzgröße oder genau im Gegenteil leistungsfähiger wird. Nichts kann Leistungsmetriken für Ihr genaues Szenario ersetzen.

Andrew
quelle
Könnten Sie bitte auf eine Dokumentation dazu verlinken? Vielen Dank.
Kapad