2010-01-21 23 views
29

Sono principalmente uno sviluppatore di Actionscript e non è affatto un esperto di SQL, ma di volta in volta devo sviluppare semplici cose da server. Quindi, pensavo di chiedere a persone più esperte la domanda nel titolo.Ha senso utilizzare un indice con una cardinalità bassa?

La mia comprensione è che non si guadagna molto impostando un indice in una colonna che conterrà pochi valori distinti. Ho una colonna che contiene un valore booleano (in realtà è un piccolo int, ma lo sto usando come flag), e questa colonna è usata nelle clausole WHERE della maggior parte delle query che ho. In un caso "medio" teorico, metà dei valori dei record sarà 1 e l'altra metà, 0. Quindi, in questo scenario, il motore del database potrebbe evitare una scansione completa della tabella, ma dovrà comunque leggere un sacco di righe (righe totali/2).

Quindi, dovrei fare di questa colonna un indice?

Per la cronaca, sto usando Mysql 5, ma sono più interessato a una logica generale sul perché non ha senso indicizzare una colonna che so che avrà una bassa cardinalità.

Grazie in anticipo.

risposta

2

Di solito faccio un semplice test "indice" rispetto a "non avere" indice. Nella mia esperienza si ottiene la maggior parte delle prestazioni su query che utilizzano ORDER BY nella colonna indicizzata. Nel caso in cui tu abbia qualche ordinamento su quella colonna, l'indicizzazione ti aiuterà molto probabilmente.

+0

Grazie per la risposta. In questo caso, tuttavia, non sto selezionando la colonna. È solo lì per contrassegnare un record come abilitato/disabilitato. Lo sto usando per una cancellazione soft, in pratica. Ecco perché devo usarlo nella clausola WHERE della maggior parte delle query. –

2

IMHO è di utilità limitata. Presumo che nella maggior parte dei casi ci siano altri criteri che stai usando nelle tue query oltre al flag che probabilmente aiuta molto di più.

Al 50%, probabilmente farei alcuni benchmark con/senza e vedere se fa molta differenza.

8

Potrebbe valere la pena includere il campo booleano in un indice composito. Per esempio, se si dispone di un grande tavolo di messaggi che in genere hanno bisogno di essere ordinati per data, ma si hanno anche un valore booleano campo eliminata, in modo spesso interrogare in questo modo:

SELECT ... FROM Messages WHERE Deleted = 0 AND Date BETWEEN @start AND @end 

Sarà sicuramente beneficiare di avere un indice composito su Eliminato e Data campi.

+0

Grazie. Forse dovrei fare qualche ricerca sugli indici compositi (so solo che esistono, ma non li ho usati molto in realtà). Sto usando questa colonna in modo molto simile al tuo codice di esempio (anche se ci sono join e altre cose, ma la clausola WHERE ha sempre questo flag per contrassegnare l'eliminazione soft). –

56

Un indice può aiutare anche sui campi di cardinalità bassi se:

  1. Quando uno dei possibili valori è molto poco frequenti rispetto agli altri valori e si cerca di esso.

    Per esempio, ci sono pochissime donne cieche colore, in modo da questa query:

    SELECT * 
    FROM color_blind_people 
    WHERE gender = 'F' 
    

    sarebbe probabilmente beneficiare di un indice su gender.

  2. Quando i valori tendono ad essere raggruppati nell'ordine tabella:

    SELECT * 
    FROM records_from_2008 
    WHERE year = 2010 
    LIMIT 1 
    

    Anche se ci sono solo 3 anni distinte qui, i record con gli anni precedenti sono molto probabilmente aggiunti prime così tanti dischi avrebbe dovuto essere scansionato prima di restituire il primo record 2010 se non per l'indice.

  3. Quando è necessario ORDER BY/LIMIT:

    SELECT * 
    FROM people 
    ORDER BY 
         gender, id 
    LIMIT 1 
    

    Senza l'indice, sarebbe necessario un filesort. Sebbene sia un po 'ottimizzato per fare il LIMIT, sarebbe comunque necessaria una scansione completa della tabella.

  4. Quando l'indice copre tutti i campi utilizzati nella query:

    CREATE INDEX (low_cardinality_record, value) 
    
    SELECT SUM(value) 
    FROM mytable 
    WHERE low_cardinality_record = 3 
    
  5. Quando avete bisogno di DISTINCT:

    SELECT DISTINCT color 
    FROM tshirts 
    

    MySQL utilizzerà INDEX FOR GROUP-BY, e se si dispone di pochi colori, questa query sarà istantaneo anche con milioni di record.

    Questo è un esempio di uno scenario quando l'indice su un campo di cardinalità basso è più efficiente rispetto a quello su un campo di cardinalità elevato.

Nota che se DML prestazioni non è molto su un problema, allora è sicuro per creare l'indice.

Se l'ottimizzatore ritiene che l'indice sia inefficiente, l'indice non verrà utilizzato.

Problemi correlati