2010-01-28 18 views
30

Ich schäme mich etwas, das zu fragen, da ich seit Jahren mit MySQL arbeite, aber naja.Mehrere und einzelne Indizes

Ich habe eine Tabelle mit zwei Feldern, a und b. Ich werde die folgenden Abfragen darauf ausgeführt werden:

  • SELECT * FROM ... WHERE A = 1;
  • SELECT * FROM ... WHERE B = 1;
  • SELECT * FROM ... WHERE A = 1 AND B = 1;

Von der Sicht der Performance, ist mindestens eine der folgenden Konfigurationen von Indizes langsamen für mindestens eine Anfrage? Wenn ja, bitte erläutern.

  1. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b);
  2. ALTER TABLE ... ADD INDEX (a, b);
  3. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b);

Dank (beachten Sie, dass wir über nicht eindeutige Indizes sprechen)

Antwort

27

Ja, zumindest in einem Fall ist deutlich langsamer. Wenn Sie nur die folgenden Index definieren:

ALTER TABLE ... ADD INDEX (a, b); 

... dann die Abfrage SELECT * FROM ... WHERE B = 1; nicht diesen Index verwenden.

Wenn Sie einen Index mit einem zusammengesetzten Schlüssel erstellen, ist die Reihenfolge der Spalten des Schlüssels wichtig. Es wird empfohlen, zu versuchen, die Spalten im Schlüssel anzuordnen, um die Selektivität zu erhöhen, wobei die selektivsten Spalten ganz links vom Schlüssel liegen. Wenn Sie dies nicht tun und eine nicht selektive Spalte als ersten Teil des Schlüssels verwenden, riskieren Sie, den Index überhaupt nicht zu verwenden. (Quelle: Tips on Optimizing SQL Server Composite Index)

+6

Und gibt es einen Vorteil der Konfiguration # 3 statt # 1? –

+6

Ja, es könnte ein Vorteil sein. Ein zusammengesetzter Index kann ein überdeckender Index werden, wenn alle Daten in der Abfrage im Index selbst enthalten sind. Im allgemeinen wird SELECT A, B VON ... WHERE A = 1; ', schneller, wenn es den zusammengesetzten Index auf' (A, B) 'verwendet, da die Abfrage keine Daten von der Tabelle abrufen muss . Die Daten sind bereits im Index. –

+1

Denken Sie daran, dass Indizes Speicherplatz beanspruchen und bei Einfügungen und Aktualisierungen möglicherweise etwas Leistung beeinträchtigen. Ich würde mit Option 3 nur gehen, wenn Ihre Anwendung Abfragen ausführen wird, die den zusätzlichen Index rechtfertigen ... Tipps für einen abdeckenden Index: http://www.sql-server-performance.com/tips/covering_indexes_p1.aspx –

22

Es ist sehr unwahrscheinlich, dass bloße Existenz eines Index verlangsamen eine SELECT Abfrage: Es wird einfach nicht verwendet werden.

Theoretisch kann der Optimierer fälschlicherweise mehr langen Index auf (a, b) anstatt auf (a) auswählen, um die Abfrage zu bedienen, die nur nach a sucht.

In der Praxis habe ich es nie gesehen: MySQL macht normalerweise den umgekehrten Fehler, einen kürzeren Index zu nehmen, wenn ein längerer existiert.

Update:

In Ihrem Fall eine der beiden folgenden Konfigurationen für alle Abfragen genügt:

(a, b); (b) 

oder

(b, a); (a) 

MySQL können auch zwei separate Indizes verwenden, mit index_intersect, so erstellen diese Indizes

beschleunigt auch die Abfrage mit a = 1 AND b = 1, wenn auch in geringerem Maße als alle oben genannten Lösungen.

Sie auch diesen Artikel in meinem Blog Möchten Sie folgendes lesen:

Update 2:

Scheint ich endlich Ihre Frage verstanden :)

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); 

Ausgezeichnet für a = 1 und b = 1, recht gut für a = 1 AND b = 1

ALTER TABLE ... ADD INDEX (a, b); 

Ausgezeichnet für a = 1 AND b = 1, fast ausgezeichnet für a = 1, schlecht für b = 1

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b); 

Hervorragend geeignet für alle drei Abfragen.

+0

Nun, ja, aber warum unnötige Indizes hinzufügen? –

+1

Ich denke, dass Sie das OP falsch interpretieren. Ich dachte, er fragte: "Ist einer von diesen langsamer als die anderen?" nicht "Ist einer von diesen langsamer als gar keine Indizes zu haben?" –

4

SQL wählt den Index, der die Abfrage am besten abdeckt. Ein Index für A, B deckt die Abfrage sowohl für Fall 1 und 3, aber nicht für 2 (da der Primärindex Spalte A)

So alle drei Abfragen abdecken müssen Sie zwei Indizes:

ALTER TABLE ... ADD INDEX (a, b); ALTER TABLE ... ADD INDEX (b) 
0

Für das Beispiel haben Sie Index-Set # 3 ist optimal. Mysql wählt die einzelnen A- und B-Indizes für einzelne Spalten where-Klauseln und verwendet den zusammengesetzten Index für die Where-Klausel A & B.

Verwandte Themen