2009-09-18 13 views
21

È necessario creare un indice per i campi di gruppo in base ai campi in un database Oracle?Creazione di indici per gruppi per campo?

Ad esempio:

select * 
from some_table 
where field_one is not null and field_two = ? 
group by field_three, field_four, field_five 

stavo testando gli indici ho creato per quanto sopra e l'unico indice rilevante per questa ricerca è un indice creato per field_two. Altri indici single-field o compositi creati su uno degli altri campi non verranno utilizzati per la query precedente. Questo suono è corretto?

risposta

11

Potrebbe essere corretto, ma ciò dipenderebbe dalla quantità di dati disponibili. Tipicamente creerei un indice per le colonne che stavo usando in un GROUP BY, ma nel tuo caso l'ottimizzatore potrebbe aver deciso che dopo aver usato l'indice field_two che non ci sarebbero stati abbastanza dati restituiti per giustificare l'uso dell'altro indice per il GRUPPO DI.

+1

+1 per aver menzionato l'ottimizzatore, è probabilmente la causa più probabile di questo. –

+0

Grazie per la risposta. Non avevo realizzato che il piano di spiegazione dipendesse dalla quantità di dati nella tabella. Non ci sono attualmente dati nella tabella, il che spiega perché l'ottimizzatore potrebbe aver saltato gli altri indici. In un'altra nota, sarebbe ancora utilizzato un indice composito su solo field_three e field_four senza field_five in query come quella sopra? Questo non includerebbe tutti i campi nella clausola group by. – onejigtwojig

+0

@Mark - questo lo spiega. Vedi le mie modifiche per maggiori informazioni su quali indici Oracle potrebbe utilizzare per il gruppo. –

7

No, questo può essere errato.

Se si dispone di una tabella di grandi dimensioni, Oracle può preferire derivare i campi dagli indici anziché dalla tabella, anche non esiste un singolo indice che copra tutti i valori.

Nell'ultimo articolo nel mio blog:

, v'è una query in cui Oracle non usa scansione completa della tabella, ma piuttosto unisce due indici per ottenere i valori della colonna:

SELECT l.id, l.value 
FROM t_left l 
WHERE NOT EXISTS 
     (
     SELECT value 
     FROM t_right r 
     WHERE r.value = l.value 
     ) 

Il piano è:

SELECT STATEMENT 
HASH JOIN ANTI 
    VIEW , 20090917_anti.index$_join$_001 
    HASH JOIN 
    INDEX FAST FULL SCAN, 20090917_anti.PK_LEFT_ID 
    INDEX FAST FULL SCAN, 20090917_anti.IX_LEFT_VALUE 
    INDEX FAST FULL SCAN, 20090917_anti.IX_RIGHT_VALUE 

Come si può vedere, non c'è TABLE SCAN su t_left qui.

Invece, Oracle prende gli indici id e value, li unisce in rowid e ottiene il (id, value) coppie dal risultato unirsi.

Ora, alla tua richiesta:

SELECT * 
FROM some_table 
WHERE field_one is not null and field_two = ? 
GROUP BY 
     field_three, field_four, field_five 

In primo luogo, esso non compilare, dal momento che si sta selezionando * da una tabella con una clausola GROUP BY.

È necessario sostituire * con espressioni basate sulle colonne di raggruppamento e sugli aggregati delle colonne non raggruppanti.

.probabilmente beneficiare il seguente indice:

CREATE INDEX ix_sometable_23451 ON some_table (field_two, field_three, field_four, field_five, field_one) 

, dal momento che conterrà tutto ciò sia per il filtraggio su field_two, l'ordinamento su field_three, field_four, field_five (utile per GROUP BY) e fare in modo che field_one è NOT NULL.

+1

Molto interessante - Non credo di averlo mai visto prima (dove Oracle si unirebbe a due indici ed eviterebbe del tutto il tavolo) –

+0

'@Eric Petroelje': c'è un suggerimento speciale, 'INDICE_JOIN', per forzare questo metodo . – Quassnoi

2

È necessario creare un indice per i campi di gruppo in base ai campi in un database Oracle?

No. Non è necessario, nel senso che una query verrà eseguita indipendentemente dal fatto che esistano o meno indici. Gli indici vengono forniti per migliorare le prestazioni della query.

Può, tuttavia, aiutare; ma esiterei ad aggiungere un indice solo per aiutare una query, senza pensare al possibile impatto del nuovo indice sul database.

... l'unico indice pertinente per questa query è un indice creato per field_two. Altri indici single-field o compositi creati su uno degli altri campi non verranno utilizzati per la query precedente. Questo suono è corretto?

Non sempre. Spesso un GROUP BY richiede a Oracle di eseguire un ordinamento (ma non sempre); ed è possibile eliminare l'operazione di ordinamento fornendo un indice adatto sulle colonne da ordinare.

Se è effettivamente necessario preoccuparsi delle prestazioni di GROUP BY, tuttavia, è una domanda importante su cui riflettere.

+0

upvote per "può eliminare l'operazione di ordinamento ..". A proposito di questo articolo ha maggiori dettagli http://use-the-index-luke.com/sql/sorting-grouping/indexed-group-by – waltersu

Problemi correlati