2010-02-28 3 views
65

Ich bin mit dem folgenden konfrontiert und ich bin mir nicht sicher, was Best Practice ist.Zwei einspaltige Indizes gegenüber einem zweispaltigen Index in MySQL?

Betrachten Sie die folgende Tabelle (die große erhalten):

id PK | Geber_ID FK | recipient_id FK | Datum

Ich verwende InnoDB und von was ich verstehe, erstellt es Indizes automatisch für die zwei Fremdschlüsselspalten. Ich werde aber auch viele Abfragen durchführen, bei denen ich eine bestimmte Kombination von:

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

Jede solche Kombination wird in der Tabelle eindeutig sein.

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

Antwort

76

Wenn Sie zwei einzelne Spaltenindizes haben, wird nur einer davon in Ihrem Beispiel verwendet.

Wenn Sie einen Index mit zwei Spalten haben, ist die Abfrage möglicherweise schneller (Sie sollten messen). Ein zweispaltiger Index kann auch als einzelner Spaltenindex 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, verwendet aber natürlich auch mehr Speicherplatz.

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

21

Ein abdeckenden Index wie:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id); 

... würde bedeuten, dass der Index, wenn eine Abfrage an giver_id oder eine Kombination von giver_id und recipient_id genannten verwendet werden könnte. Beachten Sie, dass Indexkriterien am weitesten links liegen - eine Abfrage, die sich nur auf recipient_id bezieht, wäre nicht in der Lage, den Deckungsindex in der von mir bereitgestellten Anweisung zu verwenden.

Außerdem kann MySQL nur einen Index pro SELECT verwenden, daher wäre ein abdeckender Index das beste Mittel, um Ihre Abfragen zu optimieren.

+4

'MySQL kann nur einen Index pro SELECT verwenden 'das ist nicht mehr wahr, es wäre nett, wenn Sie Ihre Antwort bearbeitet, um aktualisiert zu werden. – Davor

+0

Würde es Ihnen etwas ausmachen zu erklären, warum der Deckungsindex nicht von 'recipient_id' verwendet werden könnte? –

+2

@IvoPereira Bei Multi-Spalten-Indizes in MySQL können Sie alle Felder im Index von links nach rechts verwenden. Wenn Sie zum Beispiel einen 'INDEX (col1, col2, col3, col4)' 'haben, wird der Index für Suchen mit einer' WHERE'-Klausel wie 'col1 = 'A'' oder' col1 =' A 'AND col2 = angewendet 'B'' oder 'col1 =' A 'AND col2 =' B 'UND col3 =' C 'AND col4 =' D'', aber dieser spezielle Index wird nicht verwendet für' WHERE col2 =' B ' 'oder' WHERE col3 = 'C' UND col4 = 'D'', weil die Suchfelder in der Indexdefinition nicht am weitesten links liegen. Sie müssten zusätzliche Indizes hinzufügen, um diese Felder abzudecken. – Slicktrick

3

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

Eine weitere zu berücksichtigende Sache ist, wenn Sie das PK-Feld in dieser Tabelle eliminieren und den Primärschlüsselindex für die Felder giver_id und recipient_id definieren können. Du hast gesagt, dass die Kombination einzigartig ist, das würde möglicherweise funktionieren (angesichts einer Menge anderer Bedingungen, die nur du beantworten kannst). Normalerweise denke ich, dass die zusätzliche Komplexität, die hinzugefügt wird, den Aufwand nicht wert ist.

+0

Dank Mark, einer der Schlüssel ist in der Tat sehr selektiv, so 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, aber da jedes Feld auch individuell durchsuchbar sein kann, würde es einfach php Overhead hinzufügen. Außerdem wäre der neue Schlüssel eine (längere) Zeichenfolge anstelle einer (kürzeren) Ganzzahl. – Tom

0

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 zweispaltige Index erst bei einem bestimmten Grenzwert für die Datensatzgröße oder dem genauen Gegenteil leistungsfähiger wird.Nichts kann Leistungsmetriken für Ihr genaues Szenario ersetzen.

Verwandte Themen