2012-05-04 14 views
9

Ho avuto un tavolo Blah (float latitudine, longitudine galleggiante, data create_time, OWNER_ID int, .....)Oracle indice composito per condizioni di query gamma

e il mio codice fa solo una singola query

select * 
from Blah 
where latitude < l1 and latitude > l2 
and longitude < ll1 and longitude > ll2 
and create_time < t1 and create_time > t2 
and owner_id < o1 and owner_id > o2 ; 

(ovviamente i valori L1, L2, .... O1, O2 sono params dinamiche provenienti dal programma)

la mia domanda è che tipo di indice dovrei creare; indice composito? in caso di indice composito, quale colonna devo inserire per prima? quanto è efficace l'indice?

Ci ho pensato per un lungo periodo e non sono riuscito a trovare documenti dettagliati su come funziona l'indice di oracolo.

Posso trovare documenti che è implementato usando B-tree, nel nostro caso: ogni chiave nell'albero B è una tupla di quattro: (colonna1, colonna2, colonna3, colonna4) dove la relazione di ordinamento di tali tuple è definito come ordine lessicale.

poi per la query sopra esposto, ipotizzando il nostro ordine è (owner_id, create_time, latitudine, longitudine), immagino oracolo sarebbe necessario prima di ricerca binaria per il punto (o1, t1, L1, LL1), per questa operazione , l'indice è davvero utile. ma dopo, dobbiamo trovare il punto finale di questo primo interium: dobbiamo trovare (o1, t1, l1, ll2), questo può essere fatto anche con la ricerca binaria.

prossimo, dobbiamo trovare la prossima sezione che soddisfa la condizione, quindi abbiamo bisogno di find (o1, t1, lx, ll1) dove lx è il prossimo valore maggiore di l1, potremmo trovare questo dalla ricerca binaria pure. ma nel nostro caso è molto probabile che per la stessa latitudine non ci possa essere più di 1 longitudine, quindi qui la ricerca binaria non è più efficace della scansione lineare.

seguendo questo spirito, sembra che dovremmo mettere la colonna con una piccola cardinalità dell'intervallo di valori prima, in questo caso, create_time, se i nostri punti vengono creati solo in pochi giorni. anche se non facciamo mai condizioni di intervallo, ma solo condizioni di uguale (=), allora non importa quale colonna è la prima, giusto?

per renderlo più chiaro, ecco un esempio più semplice:

Diciamo che ho 2 colonne, X, Y e

nel DB, i valori per entrambi sono [1,2, ... .100], quindi abbiamo 100x100 righe

mia domanda è

select * from mytable where X > 34 and X < 78 and Y > 12 and Y < 15; 

dire che il nostro indice è su (X, Y), quindi la regola confronto tra 2 valori sono

v1 < v2 <=====> v1.x < v2.x || v1.x == v2.x && v1.y < v2.y 

data la norma imperativa sopra, possiamo vedere che i valori dell'indice sono disposti in serie come (valori per x, y):

1,1, 1,2 1,3 .... 1,100  
2,1 2,2 2,3 ......2,100 
..... 
100,1 100,2 ....... 100,100 

ora, per cercare i valori in la query, l'attraversamento di B-Tree ha bisogno di individuare (78-34-1) intervalli, quindi (78-34-1) * 2 ricerca (1 per l'inizio uno per le posizioni finali), non solo 2 ricerche.

quindi se abbiamo dimensioni superiori, l'intervallo di conta aumenta esponenzialmente con il numero di dimensioni, quindi l'indicizzazione potrebbe non essere utile più ------ questa è la mia preoccupazione

grazie mille Yang

risposta

9

Se il tuo unico obiettivo è creare un indice per ottimizzare questa query, preferiresti che le colonne dell'indice composito siano ordinate con la prima colonna più selettiva. Se i predicati su latitude eliminano sostanzialmente più file rispetto agli altri predicati, sarà più efficiente avere prima quella colonna. Se i predicati su owner_id eliminano sostanzialmente più file rispetto agli altri predicati, sarà più efficiente avere prima quella colonna.

In realtà, tuttavia, raramente creiamo indici il cui unico scopo è ottimizzare una singola query. In generale, al fine di rendere utile il sovraccarico della manutenzione dell'indice, vogliamo che i nostri indici siano utili in molte query. Nel caso di un indice composito, ciò significa ordinare le colonne in base alla probabilità che una query abbia predicati su quella colonna. Se si dispone di un indice composito su owner_id, create_time, latitude, longitude, ad esempio, è possibile utilizzarlo per query che specificano solo predicati su owner_id. Ma non si dovrebbe realisticamente utilizzare quell'indice per le query che specificano solo predicati su longitude.

3

Innanzitutto, tenere presente che la "B" in "B-Tree" non è "binario".

In secondo luogo, quando si tratta di indicizzazione in Oracle si ha anche la scelta di un indice bitmap se:

  1. Hai una licenza enterprise edition
  2. Non avete molte sessioni contemporaneamente modificare la tabella
  3. per i valori indicizzati non sono vicino ad essere uniche (dichiarazioni che indici bitmap sono utilizzabili solo per le colonne bassa cardinalità sono generalmente esagerata)

One tipo di query che gli indici bitmap eccellono nel combinare in modo efficiente i predicati su più colonne, in particolare dove varia il set di colonne previste (che potrebbe non essere il tuo caso, ovviamente). Se si soddisfano le tre condizioni di cui sopra, sarebbe opportuno valutare l'effetto di avere quattro indici bitmap separati sul tavolo.

+0

grazie, ma al momento mi occupo solo del problema dell'indice B-tree; anche se in pratica Oracle potrebbe utilizzare l'indice bitmap, come hai sottolineato –

0

questa tabella è utilizzata per OLTP o come DWH? se non si dispone di molte istruzioni DML con riga singola/multithread su questa tabella, è possibile utilizzare gli indici bitmap. Gli indici bitmap consentono agli operatori ROWID AND tra più indici (trasformazione stella Aka). per farlo crea un indice bitmap su ogni colonna. Come ho detto, questa soluzione si adatta meglio al sistema DWH in cui si dispone di un singolo inserto batch.

0

Le query di intervallo multidimensionale sono gestite al meglio, IMHO, al di fuori degli indici B-tree standard. Alcuni documenti sull'argomento generale possono essere trovati da una ricerca web su "query di intervallo multidimensionale".

Oracle fornisce un prodotto denominato Oracle Spatial. La documentazione di questo prodotto include, in Chapter 4, esempi e spiegazioni sulla creazione di indici spaziali e query eseguite. Non c'è una nuova sintassi SQL; il loro esempio per la creazione dell'indice è:

CREATE INDEX territory_idx ON territories (territory_geom) 
    INDEXTYPE IS MDSYS.SPATIAL_INDEX; 

che crea un indice R-tree.

Penso che l'esistenza di alberi R, alberi kdb e strutture spaziali simili sia la prova del fatto che gli alberi B standard non sono probabilmente adatti a questo tipo di applicazioni.

1

Una soluzione di forza bruta semplice consiste nel creare più combinazioni di indici sulla stessa tabella, eseguire la query con EXPLAIN PLAN attivata, quindi scegliere l'indice che il DBMS preferisce utilizzare.

Problemi correlati