2015-09-06 18 views
5

Ich habe viele Tabellen, wo ich Indizes für Fremdschlüssel und Clustered-Indizes, die diese Fremdschlüssel enthalten. Zum Beispiel habe ich eine Tabelle wie folgt aus:Overhead von Composite-Indizes

TABLE: Item 
------------------------ 
id  PRIMARY KEY 
owner FOREIGN KEY 
status 

... many more columns 

MySQL Indizes für Primär- und Fremdschlüssel erzeugt, aber manchmal möchte ich die Abfrageleistung verbessern, so werde ich gruppierten oder Abdeckung Indizes erstellen. Dies führt zu Indizes mit überlappenden Spalten.

INDEXES ON: Item 
------------------------ 
idx_owner (owner) 
idx_owner_status (owner, status) 

Wenn ich fallen gelassen idx_owner, zukünftige Anfragen, die normalerweise nur idx_owneridx_owner_status verwenden würde würde verwenden, da es owner als die erste Spalte im Index hat.

Lohnt es sich, idx_owner herum zu halten? Gibt es einen zusätzlichen I/O-Overhead, um idx_owner_status zu verwenden, obwohl MySQL nur einen Teil des Index verwendet?

Edit: Ich bin wirklich nur in der Art interessiert InnoDB verhält sich in Bezug auf Indizes.

Antwort

5

Kurze Antwort Lassen Sie den kürzeren Index fallen.

Lange anwser Dinge zu beachten:

Drop it:

  • Jeder INDEX eine separate BTree ist, die auf der Festplatte befindet, so dass es Platz in Anspruch nimmt.
  • Jede INDEX wird aktualisiert (früher oder später), wenn Sie eine neue Zeile oder eine UPDATE eine indizierte Spalte ändert. Dies erfordert einen gewissen CPU- und E/A- und Pufferpool-Platz für den "Änderungspuffer".
  • Beliebige funktionale Verwendung (im Gegensatz zur Leistung) für den kürzeren Index kann durch die längere durchgeführt werden.

Sie es nicht fallen:

  • Je länger Index sperriger als die kürzere ist. Es ist also weniger cachefähig. Also (in extremen Situationen) mit der sperrigen anstelle der kürzeren könnte mehr E/A verursachen. Ein Fall, der dies verschlimmert: INDEX(int, varchar255).

Es ist sehr selten, dass das letzte Element wirklich die anderen Elemente überschreibt.

Bonus

A "bedeckt" Index ist eine, die in einem SELECT genannten alle die Spalten enthält.Zum Beispiel:

SELECT status FROM tbl WHERE owner = 123; 

Diese nur die BTree für INDEX(owner, status) berühren, um dadurch deutlich schneller sein als

SELECT status, foo FROM tbl WHERE owner = 123; 

Wenn Sie wirklich diese Abfrage müssen schneller sein, ersetzen Sie dann beide Ihrer Indizes mit .

PK in Sekundärschlüssel

Ein weiterer Leckerbissen ... In InnoDB, die Spalten der PRIMARY KEY sind jedem Sekundärschlüssel implizit angehängt. So sind die drei Beispiele wirklich

INDEX(owner, id) 
INDEX(owner, status, id) 
INDEX(owner, status, foo, id) 

Weitere Diskussion in meinen Blogs auf composite indexes und index cookbook.