2010-02-28 8 views
65

Mi trovo di fronte a quanto segue e non sono sicuro di quale sia la prassi migliore.Due indici a colonna singola vs un indice a due colonne in MySQL?

Si consideri la seguente tabella (che otterrà grande):

id PK | giver_id FK | recipient_id FK | data

Sto utilizzando InnoDB e da quello che ho capito, crea indici automaticamente per le due colonne chiave esterna. Tuttavia, farò anche molte domande in cui dovrò abbinare una particolare combinazione di:

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

Ogni combinazione sarà unica nella tabella.

C'è qualche vantaggio dall'aggiunta di un indice a due colonne su queste colonne, o i due indici individuali in teoria sarebbero sufficienti/gli stessi?

risposta

76

Se si dispone di due indici a colonna singola, nel proprio esempio verrà utilizzato solo uno di essi.

Se si dispone di un indice con due colonne, la query potrebbe essere più veloce (è necessario misurare). Un indice a due colonne può anche essere utilizzato come indice a colonna singola, ma solo per la colonna elencata per prima.

A volte può essere utile avere un indice su (A, B) e un altro indice su (B). Questo rende le query che utilizzano una o entrambe le colonne velocemente, ma ovviamente utilizza anche più spazio su disco.

Quando si scelgono gli indici, è necessario considerare anche l'effetto sull'inserimento, l'eliminazione e l'aggiornamento. Altri indici = aggiornamenti più lenti.

21

Un indice di copertura come:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id); 

... significherebbe che l'indice potrebbe essere utilizzato se una query cui giver_id, o una combinazione di giver_id e recipient_id. Ricorda che i criteri dell'indice sono quelli più a sinistra - una query che si riferisce solo a recipient_id non sarebbe in grado di utilizzare l'indice di copertura nell'istruzione che ho fornito.

Inoltre, MySQL può utilizzare solo un indice per SELECT, quindi un indice di copertura sarebbe il mezzo migliore per ottimizzare le query.

+4

'MySQL può utilizzare solo un indice per SELECT', questo non è più vero, sarebbe bello se la tua risposta fosse aggiornata. – Davor

+0

Ti dispiacerebbe spiegare perché l'indice di copertura non potrebbe essere utilizzato da 'recipient_id'? –

+2

@IvoPereira Gli indici a colonne multiple in MySQL consentono di utilizzare tutti i campi dell'indice da sinistra a destra. Ad esempio se si ha un 'INDICE (col1, col2, col3, col4) 'allora l'indice verrà applicato per le ricerche con una clausola' WHERE' come 'col1 =' A'' o' col1 = 'A' AND col2 = 'B'' o 'col1 =' A 'AND col2 =' B 'AND col3 =' C 'AND col4 =' D'', ma questo indice particolare non sarà usato per qualcosa come 'WHERE col2 = 'B' 'o' WHERE col3 = 'C' AND col4 = 'D''perché i campi di ricerca non sono più presenti nella definizione dell'indice. Dovresti aggiungere altri indici per coprire quei campi. – Slicktrick

3

Se uno degli indici di chiave esterna è già molto selettivo, il motore di database deve utilizzarlo per la query specificata. La maggior parte dei motori di database utilizza una sorta di euristica per poter scegliere l'indice ottimale in quella situazione. Se nessuno dei due indici è altamente selettivo di per sé, probabilmente ha senso aggiungere l'indice costruito su entrambe le chiavi poiché si dice che userete quel tipo di query molto.

Un'altra cosa da considerare è se è possibile eliminare il campo PK in questa tabella e definire l'indice della chiave primaria nei campi giver_id e recipient_id. Hai detto che la combinazione è unica, quindi potrebbe funzionare (date molte altre condizioni alle quali solo tu puoi rispondere). In genere, penso che la complessità aggiunta che aggiunge non valga la pena.

+0

Grazie Mark, uno dei tasti è davvero molto selettivo, quindi dovrebbe andare bene. Ho deciso di mantenere i due indici (automatici) sul posto e vedere come si comporta nel tempo. Ho anche pensato a un donatore combinato: la chiave primaria del destinatario, ma dato che ogni campo deve anche essere ricercabile individualmente, aggiungerebbe semplicemente php overhead. Inoltre, la nuova chiave sarebbe una stringa (più lunga) anziché un intero (più breve). – Tom

0

Un'altra cosa da considerare è che le caratteristiche di prestazioni di entrambi gli approcci si baseranno sulla dimensione e sulla cardinalità dell'insieme di dati. È possibile che l'indice a 2 colonne diventi solo più performante a una determinata soglia di dimensione del set di dati o l'esatto contrario.Nulla può sostituire le metriche di rendimento per il tuo scenario esatto.

Problemi correlati