Due indici a colonna singola contro un indice a due colonne in MySQL?


114

Mi trovo di fronte a quanto segue e non sono sicuro di quale sia la migliore pratica.

Considera la seguente tabella (che diventerà grande):

id PK | giver_id FK | recipient_id FK | Data

Sto usando InnoDB e da quello che ho capito, crea automaticamente gli indici per le due colonne di chiavi esterne. Tuttavia, farò anche molte query in cui ho bisogno di abbinare una particolare combinazione di:

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

Ciascuna di queste combinazioni sarà unica nella tabella.

C'è qualche vantaggio nell'aggiungere un indice a due colonne su queste colonne o i due indici individuali in teoria sarebbero sufficienti / uguali?


1
Se la combinazione delle due colonne è unica, potresti creare un indice a due colonne con funzionalità uniche che non solo aumenteranno la velocità della tua query ma aggiungeranno anche coerenza alla tua tabella.
sguven

"MySQL può utilizzare indici a più colonne per query che testano tutte le colonne dell'indice o query che testano solo la prima colonna, le prime due colonne, le prime tre colonne e così via. Se specifichi le colonne a destra ordine nella definizione dell'indice, un singolo indice composito può velocizzare diversi tipi di query sulla stessa tabella. " - Indici a più colonne
AlikElzin-kilaka

Per estrapolare su @ user1585784; Se la combinazione delle due colonne è unica, penso che si dovrebbe usare una chiave univoca per loro. Infatti, se si vuole imporre l'unicità a livello di database, una chiave univoca è il modo più semplice per andare ...
Erk

Risposte:


133

Se hai due indici a colonna singola, nel tuo esempio verrà utilizzato solo uno di essi.

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

A volte può essere utile avere un indice su (A, B) e un altro su (B). Ciò rende veloci le query che utilizzano una o entrambe le colonne, 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. Più indici = aggiornamenti più lenti.


1
"MySQL può utilizzare indici a più colonne per query che testano tutte le colonne dell'indice o query che testano solo la prima colonna, le prime due colonne, le prime tre colonne e così via. Se specifichi le colonne a destra ordine nella definizione dell'indice, un singolo indice composito può velocizzare diversi tipi di query sulla stessa tabella. " - Indici a più colonne
AlikElzin-kilaka

33

Un indice di copertura come:

ALTER TABLE your_table ADD INDEX (giver_id, recipient_id);

... significherebbe che l'indice potrebbe essere utilizzato se si fa riferimento a una query giver_ido una combinazione di giver_ide recipient_id. Tieni presente che i criteri dell'indice sono basati sull'estrema sinistra, una query che si riferisce solo arecipient_id non sarebbe in grado di utilizzare l'indice di copertura nella dichiarazione che ho fornito.

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


10
MySQL can only use one index per SELECTquesto non è più vero, sarebbe bello se modificassi la tua risposta per aggiornarla.
Davor

Le dispiacerebbe spiegare perché l'indice di copertura non può essere utilizzato da recipient_id?
Ivo Pereira

2
@IvoPereira Gli indici a più colonne in MySQL ti consentono di utilizzare tutti i campi dell'indice da sinistra a destra. Ad esempio, se si dispone di un, INDEX (col1, col2, col3, col4)l'indice verrà applicato per le ricerche con una WHEREclausola come col1 = 'A'o col1 = 'A' AND col2 = 'B'o col1 = 'A' AND col2 ='B' AND col3 = 'C' AND col4 = 'D', ma questo particolare indice non verrà utilizzato per nulla di simile WHERE col2 = 'B'o WHERE col3 = 'C' AND col4 = 'D'perché i campi di ricerca non sono più lasciati nella definizione dell'indice. Dovresti aggiungere ulteriori indici per coprire quei campi.
Slicktrick

"un indice per SELECT" , è ancora vero per mariadb 10.1?
oldboy

1
@ Anthony: No. vedi il commento di Davor sopra.
kapad

4

Se uno degli indici di chiave esterna è già molto selettivo, il motore di database dovrebbe 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é dici che utilizzerai molto quel tipo di query.

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


Grazie Marco, uno dei tasti è davvero molto selettivo quindi dovrebbe andare bene. Ho scelto di mantenere i due indici (automatici) in posizione e vedere come si comportano nel tempo. Ho anche pensato a un donatore combinato: la chiave primaria del destinatario, ma poiché ogni campo deve essere ricercabile individualmente, aggiungerebbe semplicemente un overhead php. Inoltre, la nuova chiave sarebbe una stringa (più lunga) invece di un numero intero (più corto).
Tom,

2

Un'altra cosa da considerare è che le caratteristiche delle prestazioni di entrambi gli approcci saranno basate sulle dimensioni e sulla cardinalità del set di dati. Potresti scoprire che l'indice a 2 colonne diventa più performante solo a una determinata soglia di dimensione del set di dati, o l'esatto opposto. Niente può sostituire le metriche delle prestazioni per il tuo scenario esatto.


potresti per favore link ad alcuni documenti su questo. Grazie.
kapad
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.