SQLSERVER DISPERATO

mercoledì 16 dicembre 2009 - 18.31

MagoDaniel1981 Profilo | Newbie

Buongiorno, ho la seguente query che ha un tempo di esecuzione medio stimato di 1 minuti, anche più, e ovviamente manda in timeout i server.
Il concetto è questo:
Tabella Nominativi: qualche milione di record, tipo elenco guida del telefono
Tabella NominativiInLista: semplice unione dell'ID del nominativo e dell'ID della lista a cui fa capo
Tabella Liste: Elenco delle liste di cui sopra
Tabella NominativiInListaRIchiami: e si perchè il nominativo può appartenere ad una lista normale o ad una lista richiami. In entrambi i casi, se appartiene ad una lista normale il cui stato Eliminata = 0 AND Conclusa = 0 allora il nominativo non deve essere estrapolato dalla query.

Che fare? Qualcuno mi sa dire come sveltirla? Faccio presente che la tabella Nominativi contiene qualche milione di record e che uso SqlExpress su un server virtuale con in esecuzione 2003 Srv inglese. Ci sto lavorando da settimane ma proprio non so come fare per far si che il piano di esecuzione sia più rapido.

Non so veramente più che fare, spero sia chiaro il problema per aggiustare questa query così "malvagia".

SELECT TOP(1000)
LR.idListaRichiami,
LN.idLista,
NIL.idNominativo,
N.*,
COALESCE (AddolcitoriSuNominativi.StatoAddolcitore, '7') as StatoAddolcitore

FROM
((((Nominativi as N LEFT JOIN AddolcitoriSuNominativi ON N.idCliente = AddolcitoriSuNominativi.idNominativo)
LEFT JOIN NominativiInLista as NIL on N.idCliente = NIL.idNominativo)
FULL JOIN ListeNominativi as LN on NIL.idLista = LN.idLista)
FULL JOIN NominativiInListaRichiami as NILR ON N.idCliente = NILR.idNominativo)
FULL JOIN ListeRichiami as LR on NILR.idListaRichiamo = LR.idListaRichiami

WHERE
(N.Provincia like 'PV' AND N.Citta Like 'BRONI' AND N.Cap Like '%'
AND (NIL.idNominativo NOT IN
(Select idNominativo
From NominativiInLista
INNER JOIN ListeNominativi ON NominativiInLista.idLista = ListeNominativi.idLista
WHERE
NominativiInLista.idNominativo = NIL.idNominativo
AND ((ListeNominativi.Conclusa = 0) OR (ListeNominativi.Eliminata = 0)))))
AND (LR.idListaRichiami IS NULL)
AND ((StatoAddolcitore = '1' OR StatoAddolcitore = '2' OR StatoAddolcitore = '3' OR StatoAddolcitore = '4' OR StatoAddolcitore = '5' OR StatoAddolcitore = '6' OR StatoAddolcitore = '7' OR StatoAddolcitore IS NULL)) AND (N.Richiamabile = '1')


Grazie a tutti
Daniel

gabriel81 Profilo | Junior Member

Non sono molto esperto, però da come l'hai postata effettivamente è un bel carico..

Le performance del sistema operativo come sono in fase di querying?
Bisognerebbe forse prima capire se il collo di bottiglia è l' SQL (indici & Co. ) oppure proprio l'hardware che non ce la fa a star dietro a SQL..

http://www.myspace.com/madmack1981

MagoDaniel1981 Profilo | Newbie

Ciao e grazie intanto per la rapida risposta. No credo che il collo sia proprio dato dalla query non felice in termini di piano di esecuzione. è infatti molto lenta anche qui da me in locale sul portatile di prova che è comunque una gran bella macchina. Temo proprio che quei milioni di righe intasino tutto ma ovviamente devo usarle!
Tra l'altro ho provato a fare delle modifiche strutturali delle tabelle incriminate ma la Nominativi non può nemmeno più essere cambianta, infatti se provo ad aggiungere degli indici su alcuni campi Il management studio 2005 va in timeout anche lui dopo 1 minuti e non mi modifica la tabella.

Che consigli? Cosa può effettivamente velocizzare un po' il tutto? Serve che ti alleghi piano di esecuzione così come viene visualizzato in Management studio? Io mastico di database ma non son un guru e mi sa che in questo caso mi sono scontrato con i miei limiti di conoscenze!

Grazie ancora per l'interessamento.

Buon lavoro.
Daniel

P.S vedo dal myspace che canti! Io suono la batteria in una band tributo Pearl Jam!
Keep on rockin' quindi!
www.myspace.com/ontwolegscoverband

lbenaglia Profilo | Guru

>Che fare? Qualcuno mi sa dire come sveltirla?
E' semplicemente impossibile suggerirti una soluzione dato che occorrerebbe conoscere tante di quelle cose che si farebbe prima a loggarsi al sistema ed eseguire una analisi mirata

>e che uso SqlExpress su un server virtuale con in esecuzione
>2003 Srv inglese.
I data files dove risiedono? Su una LUN montata via fibra/iSCSI?

>Non so veramente più che fare, spero sia chiaro il problema per
>aggiustare questa query così "malvagia".
>
>FROM
>((((Nominativi as N LEFT JOIN AddolcitoriSuNominativi ON N.idCliente
>= AddolcitoriSuNominativi.idNominativo)
>LEFT JOIN NominativiInLista as NIL on N.idCliente = NIL.idNominativo)
>FULL JOIN ListeNominativi as LN on NIL.idLista = LN.idLista)
>FULL JOIN NominativiInListaRichiami as NILR ON N.idCliente =
>NILR.idNominativo)
>FULL JOIN ListeRichiami as LR on NILR.idListaRichiamo = LR.idListaRichiami
FULL JOIN? A che servono le FULL JOIN?!

>WHERE
>(N.Provincia like 'PV' AND N.Citta Like 'BRONI'
Che senso ha scrivere una condizione di LIKE senza alcuna wildcard?

>AND N.Cap Like '%'
Che senso ha scrivere una condizione di LIKE con solo una wildcard?

>AND (NIL.idNominativo NOT IN
L'operatore NOT IN è quanto di più lento esista.

>(Select idNominativo
>From NominativiInLista
>INNER JOIN ListeNominativi ON NominativiInLista.idLista = ListeNominativi.idLista
>WHERE
>NominativiInLista.idNominativo = NIL.idNominativo
>AND ((ListeNominativi.Conclusa = 0) OR (ListeNominativi.Eliminata
>= 0)))))
>AND (LR.idListaRichiami IS NULL)
>AND ((StatoAddolcitore = '1' OR StatoAddolcitore = '2' OR StatoAddolcitore
>= '3' OR StatoAddolcitore = '4' OR StatoAddolcitore = '5' OR
>StatoAddolcitore = '6' OR StatoAddolcitore = '7' OR StatoAddolcitore
>IS NULL)) AND (N.Richiamabile = '1')
L'utilizzo eccessivo di operatori OR è estremamente deleterio dal punto di vista delle performance.
Come risolvere? Non conoscendo praticamente niente dell'architettura e della logica non sono in grado di auitarti.

>Grazie a tutti
Prego.

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

MagoDaniel1981 Profilo | Newbie

Ciao e grazie per l'interessamento.

La query come la vedi è una copia del codice .NET dove sono stati valorizzati i parametri per valutarne il piano ed il tempo di esecuzione. Nel codice originale ovviamente al posto di 'BRONI' c'è il parametro @Citta, idem per il cap, che viene passato al DB come wildcard se l'utente nella pagina web non specifica un valore di cap predefinito.

Il discorso invece dei tanti OR è l'unico modo che conoscono, in un'unica query, di passare N valori per un campo. Io ho infatti 7 stati addolcitore, numerici, da 1 a 7 appunto. Se l'utente mi seleziona solo gli stati 1, 3 e 6, ad esempio, la query diverrebbe =1 OR =3 OR = 6. Il codice infatti, in parte, viene scritto da una sub VB.NET che, in funzione dei parametri passati, scrive il commandText. Quello che vedi è il comando nella sua forma più lunga nel caso ad esempio l'utente richieda indifferentemente tutti e 7 gli stati dell'addolcitore. Mi rendo conto che a quel punto si farebbe prima a non mettere WHERE ADDOLCITORE = X OR Y OR Z ma tralasciare semplicemente la condizione. Ma questo cambierebbe di molto il piano di esecuzione?

Il NOT IN so che è lento, ma se devo estrarre dei nomi da una tabella che non sono già presenti in altre liste, come faccio se non così?

Per l'architettura, infine, non so dirti, credo comunque che sia tutto su una stessa macchina. E' un server virtuale su Aruba, non conosco esattamente l'architettura di rete presente.

Spero sia un po' più chiaro il discorso in generale. Tieni conto comunque che la mia necessità è estrarre N record da una tabella Nominativi (di milioni di record) i quali non siano già inclusi in una tabella che associa l'ID del nome con l'ID di un lista (altra ulteriore tabella), questo se, secondo quell'associazione, la tabella della lista primaria non è conclusa o eliminata (altrimenti il nome deve nuovamente essere selezionato in quanto non è attualmente in lavorazione). Mi rendo conto che la cosa è piuttosto complicata.

In ultimo, il discorso delle FULL JOIN se devo esser sincero non ricordo perchè è così, avevo probabilmente trovato qualche esempio che utilizzava quel sistema. Non va bene? Sono meglio dei LEFT? Cosa cambia in termini di esecuzione?

Grazie per gli approfondimenti e buon lavoro.

Daniel

lbenaglia Profilo | Guru

>In ultimo, il discorso delle FULL JOIN se devo esser sincero
>non ricordo perchè è così, avevo probabilmente trovato qualche
>esempio che utilizzava quel sistema. Non va bene? Sono meglio
>dei LEFT? Cosa cambia in termini di esecuzione?
Non è questione di meglio o peggio, è questione di righe risultanti.
Sui Books Online troverai i dettagli di ogni tipo di JOIN:
http://msdn.microsoft.com/en-us/library/ms191472.aspx

Inoltre le query non andrebbero MAI composte lato client (vedi problemi di performance a causa della creazione di un nuovo query plan ad ogni esecuzione e SQL Injection), ma andrebbero incapsulate in una stored procedure parametrica.

>Grazie per gli approfondimenti e buon lavoro.
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
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