Indici non clustered

lunedì 02 ottobre 2006 - 10.40

bule Profilo | Junior Member

dunque vediamo se riesco ad esprimere chiaramente il mio problemo

eseguo la seguente query, verso un db sql server 2005:

select *
from principale
where CONVERT(varchar(25), Tempo, 105) LIKE '19-09-2006'
--where tempo = '19/09/2006'
order by id desc


per ottenere le righe della tabella princioale relative alla giornata del 19-09-2006

ora: il campo tempo è di tipo datetime e dentro tiene conto anche delle ore, min, sec, etc
il campo id è chiave primaria ed è di tipo int, è un numero che identifica il numero della riga della tabella


tempo è impostato come indice non-clustered
id come cluster

quando visualizzo il piano di esecuzione vedo che viene fatta una index scan solo sull'indice clustered...

ho pensato che sarà colpa del convert e difatti se commento quella restriione e metto come clausola nel where quella che nel codice sql sopra è commentata il piano di eseciìuzione mi dà 50% ricerca su indice clustered e 50% su indice non clustered..

il problema è che la query giustamente non ritorna nulla perchèi valori della colonna datetime hanno anche le ore, min , e non solo il giorno


Finalmente la domanda:
- come posso sfruttare l'indice non-clustered per velocizzare la ricerca in questa situazione?
- il metodo che ho usato per estrre le righe di una giornata è da somari?

grazie mille...mi dispiace della lunghezza della domanda ma in meno spazio non ce la faceva ad esporre questo problema..

lbenaglia Profilo | Guru

>Finalmente la domanda:
>- come posso sfruttare l'indice non-clustered per velocizzare
>la ricerca in questa situazione?
>- il metodo che ho usato per estrre le righe di una giornata
>è da somari?

Ciao bule,

La condizione "where CONVERT(varchar(25), Tempo, 105) LIKE '19-09-2006'" applica la funzione di conversione alla colonna tempo PER TUTTE LE RIGHE causando uno scan dell'intera tabella (e dato che hai definito un indice clustered, verrà scansito questo indice).

I data type datetime e smalldatetime includono sia l'informazione data che quella oraria, ma puoi elegantemente aggirare il problema restituendo tutte le righe comprese tra l'inizio e la fine della giornata (ovvero dalla mezzanotte alla mezzanotte successiva - 3.33 millissecondi per il datetime o -1 minuto per smalldatetime).

Quindi la tua query sarà:

SELECT * FROM dbo.Principale WHERE Tempo BETWEEN '20060919' AND '20060919 12:59:59.997' ORDER BY id;

>grazie mille...mi dispiace della lunghezza della domanda ma in
>meno spazio non ce la faceva ad esporre questo problema..
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

bule Profilo | Junior Member

ottima questa soluzione, ci stavo pensando anche io ma no riuscivo a capire come inserire le date .

però ancora il piano di esecuzione mi dà ancora una ricerca 100% sull'indice clustered, quello non clustered su tempo non sembra considerarlo..

lbenaglia Profilo | Guru

>ottima questa soluzione, ci stavo pensando anche io ma no riuscivo
>a capire come inserire le date .
>
>però ancora il piano di esecuzione mi dà ancora una ricerca 100%
>sull'indice clustered, quello non clustered su tempo non sembra
>considerarlo..

Che succede se commenti la clausola ORDER BY?
La colonna id non fa parte dell'indice non clustered, quindi la query non risulta coperta dall'indice rendendo necessario accedere all'indice clustered. Probabilmente il query optimizer considera inefficiente utilizzare l'indice non clustered ed è per questo motivo che non lo vedi nel query plan.
Se i dati ti servono espressamente ordinati per quella colonna, potresti fare alcune prove singolarmente:

- definisci un indice non custered sulle colonne id, Tempo;
- definisci un indice non custered sulle colonne Tempo, id;
- definisci un indice non custered sulla colonna Tempo utilizzando la nuova clausola INCLUDE per inserire la colonna id nel leaf level dell'indice;
- definisci un indice non custered sulla colonna id utilizzando la nuova clausola INCLUDE per inserire la colonna Tempo nel leaf level dell'indice;

A questo punto analizza i piani di esecuzione e guarda quale combinazione è più efficiente per la tua query.
Il processo di indicizzazione è piuttosto empirico, e spesso il risultato migliore si ottiene sperimentando...

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

bule Profilo | Junior Member

se tolgo order by ancora usa solo il clustered

tra l'altro anche se metto order by tempo non lo considero

adesso faccio un po di esperimenti e poi ti dico ..grazie


Beh dopo un pò di esperimenti sono arrivato alla conclusione che è meglio cacciare un indice cluster sui tempi..che comunque anche se il campo non è univoco le ripetizioni sono molto limitate...

in questo modo le ricreche sono effettivamnte molto veloci : si passa da circa 170 letture logiche nella cache a 15

e gli inserimenti non sono penalizzati

grazie per l'attenzione
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5