2015-09-06 18 views
5

Ho molte tabelle in cui ho indici su chiavi esterne e indici cluster che includono quelle chiavi esterne. Per esempio, ho una tabella come la seguente:Overhead di indici compositi

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

... many more columns 

MySQL genera gli indici per le chiavi primarie ed esterne, ma a volte, voglio migliorare le prestazioni delle query in modo creerò indici cluster o di copertura. Questo porta ad avere indici con colonne sovrapposte.

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

Se ho lasciato cadere idx_owner, query future che normalmente utilizzare idx_owner sarebbe solo usare idx_owner_status poiché ha owner come prima colonna nell'indice.

Vale la pena conservare idx_owner? Esiste un overhead di I/O aggiuntivo per utilizzare idx_owner_status anche se MySQL utilizza solo una parte dell'indice?

Modifica: Sono interessato solo al modo in cui InnoDB si comporta in relazione agli indici.

risposta

5

Risposta breve Eliminare l'indice più breve.

lungo anwser Le cose da considerare:

rilasciarlo:

  • Ogni INDEX è un BTree separato che risiede sul disco, quindi ci vuole spazio.
  • Ogni INDEX viene aggiornato (prima o poi) quando si INSERT una nuova riga o UPDATE modifica una colonna indicizzata. Ciò richiede un po 'di CPU, I/O e spazio buffer_pool per il' buffer di modifica '.
  • Qualsiasi funzionale l'utilizzo (al contrario delle prestazioni) per l'indice più breve può essere eseguito da quello più lungo.

Non far cadere esso:

  • L'indice è più ingombrante di quello più breve. Quindi è meno in cache. Quindi (in situazioni estreme) utilizzando uno più ingombrante al posto del più corto potrebbe causare più I/O. Un caso che aggrava questo: INDEX(int, varchar255).

È molto raro che l'ultimo elemento sovrascriva effettivamente gli altri elementi.

bonus

A "copertura" indice è quello che contiene tutti le colonne menzionate in una SELECT.Per esempio:

SELECT status FROM tbl WHERE owner = 123; 

Questo toccherà solo la BTree per INDEX(owner, status), essendo in tal modo notevolmente più veloce di

SELECT status, foo FROM tbl WHERE owner = 123; 

Se avete veramente bisogno che query per essere più veloce, quindi sostituire sia della vostra indici con INDEX(owner, status, foo).

PK nella secondaria chiave

più Uno bocconcino ... In InnoDB, le colonne del PRIMARY KEY sono implicitamente aggiunto ad ogni chiave secondaria. Così, i tre esempi sono davvero

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

Più discussione nel mio blog sul composite indexes e index cookbook.