2009-12-10 10 views
7

Ho una tabella con un potenziale di fino a 5.000.000 di righe. Una delle colonne in questa tabella viene usata da sola nelle query, ma ci sono solo 5 possibili valori di questa colonna, e attualmente ho 10.000 righe e, secondo il piano di spiegazioni, non ha senso usare il mio indice su quella colonna.Indice su una colonna con solo 5 valori distinti - Vale la pena?

sarà mai, o non dovrei perdere tempo con un indice

Edit: Questo è il due Spiegare i piani in questo momento Without index http://img706.imageshack.us/img706/1903/noindex.png vs. With forced index via hints http://img692.imageshack.us/img692/8205/indexp.png Quest'ultima immagine forzo l'utilizzo dell'indice con un suggerimento.

+0

Dipende dalle vostre domande, ovviamente. L'esempio indica il caso in cui si sta filtrando secondo un criterio: 'FREQUENCYID'. Se prevedi di avere altri criteri in un secondo momento (magari usando una query dinamica) e filtri anche da loro, allora l'indice avrebbe più senso. –

risposta

7

Dipende da un paio di cose.

In primo luogo, la distribuzione dei valori. Se hai solo cinque valori distinti, ma uno di questi rappresenta il 99,9999% delle righe nella tabella, ovviamente non vorresti che l'ottimizzatore usasse l'indice per quel valore ma tu potresti volerlo per gli altri. In alcuni casi come questo vale la pena utilizzare un indice basato sulle funzioni per assicurarsi di indicizzare solo i valori di interesse e non quelli che occupano spazio.

In secondo luogo, ci sono interrogazioni a cui è possibile rispondere utilizzando tale indice senza accedere alla tabella?

Si noti che non è solo la percentuale di righe a cui si accede che conta, ma il numero di blocchi della tabella a cui è necessario accedere. Ad esempio se hai una tabella di 1000 blocchi e 30 righe per blocco in media e una colonna ha 30 valori distinti (ognuno dei quali è presente in 1000 righe), quindi il numero di blocchi che devono essere visitati per leggere ogni riga per un singolo valore varia tra 1000/30 = 34 (vale la pena usare un indice) e 1000 (non vale la pena usare un indice) a seconda di come vengono distribuite le righe. questo è espresso dal fattore di clustering dell'indice - se il suo valore è vicino al numero di righe nella tabella, allora l'indice ha meno probabilità di essere usato, e se è vicino al numero di blocchi allora è più probabile che sia Usato.

Inoltre, si può osservare la compressione dell'indice per vedere se ciò consente di risparmiare spazio.

Fare attenzione agli indici bitmap: non sono amichevoli ai sistemi in cui sono soggetti a modifiche da più sessioni contemporaneamente (ad esempio due persone che inseriscono contemporaneamente nello stesso file righe nella tabella indicizzata).

Una strategia più efficace se si desidera migliorare l'efficienza delle query con i predicati su questi cinque valori è utilizzare il partizionamento, in parte a causa dell'eliminazione della partizione nella query ma anche a causa del miglioramento delle statistiche disponibili per l'ottimizzatore quando sa che sarà accessibile solo una partizione e potrà utilizzare statistiche a livello di partizione anziché statistiche globali.

1

Se è goin ad aumentare di dimensioni come si parla

fino a 5.000.000 righe

mi sento di raccomandare la creazione di un indice.

1

Forse il modo più semplice per non indovinare ma in realtà provare.

Ma mi sembra che stai confrontando i piani di esecuzione per trovare l'approccio migliore. Non è affidabileL'ottimizzatore potrebbe non disporre di informazioni appropriate per scegliere il piano migliore (ad esempio, se si dispone di una distribuzione non uniforme di valori e non si dispone dell'istogramma). Anche guardare "costi" per spiegare il piano non ha senso.

Il modo migliore è confrontare gli IO logici. Esegui SQL * Plus, ad esempio set autotrace traceonly, quindi esegui la query (con e senza indice) e confronta il numero "coerente ottiene". Meno sono e meglio è.

Informazioni sull'importanza dei LIO: article by Cary Millsap.

0

Provalo con query tipiche, controlla in che direzione è più veloce.

È possibile che una scansione di tabella completa sia più veloce in media rispetto a un intervallo di scansione indice + accesso a tabella di Rowid - nel qual caso Oracle ha capito bene.

D'altra parte, forse ci sono schemi di dati che per la maggior parte delle tue query è meglio usare l'indice - nel qual caso probabilmente vorrai aggiungere l'hint INDICE.

2

L'indice sarà utile nei seguenti casi:

  • Quando si cerca infrequenti FREQUENCYID 's. Ad esempio, solo 10 delle tue 10,000,000 righe hanno FREQUENCYID = 1 e lo cerchi.

  • Quando non si utilizzano altre colonne tranne FREQUENCYID nelle query. La seguente interrogazione:

    SELECT FREQUENCYID, COUNT(*) 
    FROM mytable 
    GROUP BY 
         FREQUENCYID 
    

    beneficerà l'indice (in realtà, sarà molto probabilmente essere utilizzato INDEX FAST FULL SCAN insieme HASH AGGREGATE)

  • Quando le righe della tabella sono grandi e tutte le colonne che si utilizzano nella query sono indicizzate. In questo modo, tutti gli indici verranno uniti invece di creare un FULL TABLE SCAN. Dire, questa query:

    SELECT FREQUENCYID, OTHERCOLUMN 
    FROM mytable 
    WHERE FREQUENCYID = 2 
    

    possono essere eseguite unendo i valori dagli indici su FREQUENCYID e OTHERCOLUMN su ROWID.