2012-10-18 14 views
11

Abbiamo una tabella con più di due milioni di righe in cui tutte le query relative saranno una ricerca tra Column1 e Column2. Inoltre, ci sarà un solo risultato possibile. Per esempio ...SQL indicizzazione per query Between con una sola corrispondenza?

Col1  Col2 
1  5 
6  10 
11  15 

select * from table1 where 8 between Col1 and Col2 

Al momento ho un indice cluster univoco su Col1 e Col2. Finora non sono stato in grado di capire come ottimizzare ulteriormente la query e gli indici per ridurre al minimo le righe gestite. Il piano di esecuzione attualmente riporta il costo di quasi 0,5 e 113k righe gestite quando si individua l'unica risposta corretta.

Quali opzioni potrei trascurare?

Come richiesto, qualche particolare dal piano di esecuzione corrente:

Operation 
Clustered Index Seek 
Predicate 
CONVERT_IMPLICIT(bigint,[@2],0)<=[Col2] 
Seek Predicate 
Seek Keys[1]: End: Col1 <= Scalar Operator(CONVERT_IMPLICIT(bigint,[@1],0)) 
+0

Sarebbe utile scrivere come 'seleziona * da tabella1 dove Col1 = < 8 and Col2> = 8' – Vicki

+0

Il passo è sempre 5 in Col1? Se è così allora la risposta è semplice :) –

+0

Che aspetto ha il piano di esecuzione? Potresti aggiungerlo alla domanda? –

risposta

3

Penso di aver trovato la risposta. Ho dovuto iniziare creando un indice cluster unico su Col1, quindi creare un indice Unclustered Unclustered su Col2. La query doveva quindi essere aggiornata per forzare le ricerche su ciascun indice.

select * from table1 where Col1 = 
    (select max(Col1) from table1 where Col1 <= 8) 
and Col2 = 
    (select min(Col2) from table1 where Col2 >= 8) 

Il piano di esecuzione ora riporta il costo 0,0098 e 1 riga gestita.

1
select * from table1 where Col1 <= 8 and Col2 >= 8 

Forse il "tra" con due colonne sta causando un problema.

Inoltre, si dovrebbe avere solo 1 indice composito su entrambe le colonne (Col1, Col2).

6

Gli intervalli sono sempre non sovrapposti? Lei dice che c'è sempre una sola partita. Se lo sono, si può scrivere come:

SELECT * FROM table1 
    WHERE 8 <= Col2 
    ORDER BY Col2 ASC 
    LIMIT 1 

Questo vi darà la riga con il valore più basso di Col2, che è superiore a 8 - che è il campo che ti interessa L'indice sarebbe necessario solo su. Col2 e il costo dovrebbe essere piccolo.

Poiché non hai menzionato il DBMS che stai utilizzando, lo LIMIT 1 deve essere sostituito con quello che il tuo DB utilizza per recuperare i primi N risultati.

È necessario verificare il codice Col1 <= your_value per assicurarsi che il valore che si sta cercando sia realmente compreso nell'intervallo.

Problemi correlati