2012-08-15 16 views
5

In una tabella nella nostra installazione Oracle abbiamo una tabella con un indice su due delle colonne (X e Y). Se faccio una query sulla tabella con una clausola where che tocca solo la colonna X, Oracle sarà in grado di utilizzare l'indice?Indice Oracle con più colonne per query su singola colonna

Ad esempio:

Tabella Y: col_a, Col_B, Col_C,

Index esiste su (col_a, Col_B)

SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW'; 

verrà utilizzato l'indice o volontà si esegue una scansione della tabella?

risposta

9

Dipende.

Si potrebbe verificare che lasciando Oracle spiegare il piano di esecuzione:

EXPLAIN PLAN FOR 
    SELECT * FROM Table_Y WHERE Col_A = 'STACKOVERFLOW'; 

e poi

select * from table(dbms_xplan.display); 

Così, per esempio con

create table table_y (
    col_a varchar2(30), 
    col_b varchar2(30), 
    col_c varchar2(30) 
); 

create unique index table_y_ix on table_y (col_a, col_b); 

e poi un

explain plan for 
    select * from table_y 
    where col_a = 'STACKOVERFLOW'; 

select * from table(dbms_xplan.display); 

Il piano (sulla mia installazione) si presenta come:

------------------------------------------------------------------------------------------ 
| Id | Operation     | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT   |   |  1 | 51 |  1 (0)| 00:00:01 | 
| 1 | TABLE ACCESS BY INDEX ROWID| TABLE_Y |  1 | 51 |  1 (0)| 00:00:01 | 
|* 2 | INDEX RANGE SCAN   | TABLE_Y_IX |  1 |  |  1 (0)| 00:00:01 | 
------------------------------------------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - access("COL_A"='STACKOVERFLOW') 

ID 2 si mostra, che l'indice TABLE_Y_IX è infatti utilizzato per un index range scan.

Se su un'altra installazione Oracle sceglie di utilizzare l'indice dipende da molte cose. È lo strumento di ottimizzazione delle query di Oracle che prende questa decisione.

Aggiornamento Se ti senti essere meglio (prestazioni saggia, che è) se Oracle utilizzato l'indice, si potrebbe desiderare di provare il + index_asc(...) (vedi index hint)

Quindi nel tuo caso che avrebbe essere qualcosa come

SELECT /*+ index_asc(TABLE_Y TABLE_Y_IX) */ * 
    FROM Table_Y 
WHERE Col_A = 'STACKOVERFLOW'; 

Inoltre, vorrei assicurarsi di aver raccolto statistiche sul tavolo e le sue colonne. È possibile controllare la data dell'ultima raccolta di statistiche con un

select last_analyzed from dba_tables where table_name = 'TABLE_Y'; 

e

select column_name, last_analyzed from dba_tab_columns where table_name = 'TABLE_Y'; 

Se non ci sono statistiche o se sono stantio, prendere dimestichezza con il pacchetto dbms_stats per raccogliere tali statistiche.

Queste statistiche sono i dati che l'ottimizzatore di query fa molto affidamento sulle proprie decisioni.

+0

Perfetto, questo aiuta molto.Per inciso, la mia installazione riporta una scansione della tabella, ma almeno ora ho la possibilità di controllare. –

+0

Solo chiedendo. La selezione del piano di esecuzione non dipende dalla scelta della prima o della seconda colonna dell'indice. Cioè se si sceglie la prima colonna si ottiene una scansione dell'intervallo di indice, ma se si seleziona la seconda colonna si ottiene una scansione completa della tabella? – Gisli

+1

@Gisli: Oracle potrebbe scegliere di utilizzare l'indice per [index skip scan] (http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#PFGRF10105) nel proprio scenario. –

Problemi correlati