Newsgroup: it.comp.lang.visual-basic
Titolo: Indice su tabella peggiora prestazioni

Scusate se sono OT,
dal mio programma, eseguo una query per aggiornare un totale di una
tabella:
UPDATE TABELLA TA SET TA.TOTALE=TA.TOTALE + 
(SELECT SUM(C.IMPORTO) FROM TABELLARIGHI C INNER JOIN TABELLATESTA CONT ON
C.CODICE=CONT.CODICE WHERE C.DARECLIFOR=TA.CODCLIFOR AND
(TABELLATESTA.CODICE BETWEEN '1' AND '5000' AND TABELLATESTA.DATAREG
BETWEEN '01-01-2006' AND '12-31-2006'));
Se indicizzo TABELLATESTA.DATAREG la query diviene molto lenta, se non lo
metto tutto avviene normalmente.
Ho pensato ad un bug del Firebird (il database che uso), ora cercherò di
documentarmi, avete qualche altra idea?
Grazie
-- 
DBMS Firebird
VB6 + Ado

 documentarmi, avete qualche altra idea?
Due:
1) Datareg e' un campo che si autoaggiorna ogni volta che modifichi un
record?
2) Non sempre un indice in piu' e' sinonimo di prestazioni migliori;
per esempio, per questioni di ordinamento dell'indice...

 per esempio, per questioni di ordinamento dell'indice...
Io credo che firebird dis-ottimizzi la query usando un piano diverso quando
trova l'indice sulla data.
Il piano sarebbe tipo la traduzione della query con l'esplicazione degli
indici da usare, o roba simile.
Comunque per ora l'ho tolto, ma vorrei capire il perchè ^_^.



Beh, se FireBird e' sufficentemente avanzato da cambiare piano di
esecuzione a seconda degli indici, forse ha anche uno strumento che ti
mostra il piano in questione. Partendo da quello magari qualcosa
capiamo :-)
In alternativa, almeno elenca gli indici prima e dopo, senno' c'e' poco
materiale con cui lavorare :-)

 materiale con cui lavorare :-)
Guarda mi è entrata una cosa urgentissima.
Domani mattina rispondo al post :)
Grazie per ora.


 materiale con cui lavorare :-)
UPDATE TABELLA TA SET TA.TOTALE=TA.TOTALE + 
(SELECT SUM(C.IMPORTO) FROM TABELLARIGHI C INNER JOIN TABELLATESTA CONT ON
C.CODICE=CONT.CODICE WHERE C.DARECLIFOR=TA.CODCLIFOR AND
(TABELLATESTA.CODICE BETWEEN '1' AND '5000' AND TABELLATESTA.DATAREG
BETWEEN '01-01-2006' AND '12-31-2006'));
Allora l'unico indice che cambia è TABELLATESTA.DATAREG.
Gli altri coinvolti sono:
TA.CODCLIFOR (varchar(7))
C.DARECLIFOR(varchar(7))
C.CODICE (numeric)'quello del piano di cui sopra
CONT.CODICE (Numeric)'quello del piano di cui sopra
Tnx


 documentarmi, avete qualche altra idea?
Il DB2 IBM per mainframe, almeno nelle vecchie versioni, aveva qualche
avversità nel gestire il between con campi indicizzati.
Prova con ... AND TABELLATESTA.DATAREG >= '01-01-2006' AND AND
TABELLATESTA.DATAREG <= '12-31-2006' al posto della between
Paolo

 TABELLATESTA.DATAREG <= '12-31-2006' al posto della between
Ti ringrazio, ma purtroppo pare non funzionare :\
Vabbè per ora lascio senza indice :)


 CONT.CODICE (Numeric)'quello del piano di cui sopra
Al momento sono pesantemente influenzato e febbricitante, oltre che
essere in ufficio a lavorare...quindi non sono lucidissimo e non ho
molta voglia di scrivere.
Cmq, l'intera cosa ha un senso, gia' vista a suo tempo con SQL su un
mio DB. In pratica aggiungendo un indice, la query di ricerca
rallentava brutalmente.
L'ipotesi piu' probabile, IMHO, e' quanto segue:
Quando lanci una query il DBE usa tutti gli indici che riesce a
trovare, visto che in teoria piu' indici usa piu' veloce e' la ricerca.
Ma metti ad esempio che aggiungendone uno cambi anche l'ordine in cui
gli indici vengono usati.
La tua query usa diversi criteri nello Where. Senza indice sulla data,
il DBE usa l'indice sul campo CODICE e tira fuori un limitato numero di
record, poi esegue la ricerca per data su pochi record.
Ad un certo punto decidi di aggiungere l'indice per data: a quel punto
il DBE decide di usare prima quello, tira fuori un milione di record in
un botto di tempo, poi applica l'altro indice e l'altro criterio di
ricerca e tira fuori i soliti 5-6 record in un attimo.
Non so se riesco a spiegarmi...
Oppure puo' essere un problema di ordinamento dell'indice: se l'indice
e' ordinato decrescente, e tu fai la ricerca con i criteri crescenti,
l'indice serve a poco (ed il contrario)...
Insomma, di motivi ce potrebbero essere parecchi, specie quando si
parla di indici su query con Join, solo che oggi ho finito le pile :-\

Andrea [Work] ha scritto:

Non esiste tra i vari ToolManager di firebird un query Analizer....? In
modo da valutare i piani di esecuzione della query e capire dove stai
sbagliando, o almeno dove si può intervenire per ottimizzare..??
@Alex

 Vabbè per ora lascio senza indice :)
Hai molti indici sulla TABELLATESTA ?
Per caso ne hai qualcuno che comprende anche DATAREG, anche se non come
primo campo ?
Paolo

 sbagliando, o almeno dove si può intervenire per ottimizzare..??
Si, nella ma non nell'update.
Se la trasformo in select i piani che tira fuori sono gli stessi con o
senza indice.
Comunque a me va bene così, sono passato da un'elaborazione da 5 minuti ->
a 7 secondi, oppure se vogliono filtrare i dati per non elaborare tutta la
tabella, saranno un 30/40 secondi, ovvero in linea alle aspettative più
rosee.
Al 90% verrà fatta la stampa globale, quindi in 7secondi se la tolgono.
Io penso che il problema sia
UPDATE TABELLA TA SET campo = (Select ...... FROM TB WHERE .... AND
TA.id=TB.id)
Perchè se isolo la select semplice, i piani sono uguali, e non posso
simulare il TA.id=TB.id.


 primo campo ?
Non credo di avere molti indici, anche perchč una query diversa mi pare
possa benificiare di quell'indice.
Comunque per ora non ne ho bisogno :)
Trall'altro la parte where dell'esempio equivale a non usarla, cioč:
(TABELLATESTA.CODICE BETWEEN '1' AND '5000' AND TABELLATESTA.DATAREG
BETWEEN '01-01-2006' AND '12-31-2006'));
Codice nella tabella c'č solo da 1 a 5000, e datareg sono compresi solo in
quell'intervallo. Quindi in quel caso possono fare la stampa senza filtrare
i dati, che impiega 7 secondi (questa sui 30/40sec, prima delle modifiche 5
minuti).


 parla di indici su query con Join, solo che oggi ho finito le pile :-\
Ti ringrazio :)
