Principale utente con più risposte
Lentezza in esecuzione select

Domanda
-
Ciao a tutti.
Devo compiere un intervento da un Cliente il quale, in autonomia, ha cambiato macchina SQL e soltanto adesso mi coinvolge.
Il problema "di base" (gli altri eventuali li vedrò) è che una query piuttosto banale di SELECT con condizione "where", su una tabella di dimensioni medio basse , sulla vecchia macchina impiegava un secondo mentre sull'attuale più di dieci.
Mi riferiscono che dopo un riavvio dei servizi di MSSQLServer, la query diventi velocissima ma con il passare del tempo, la stessa query, torni ad essere lenta come in precedenza. La ricostruzione degli indici è già stata effettuata.
Sono consapevole che le informazioni al momento sono poche e frammentarie ma... avete una qualche idea almeno su quale strada devo concentrare le mie ricerche e quali strumenti posso utilizzare per una buona analisi del problema ?
Grazie a tutti in anticipo.
Hunternet
Risposte
-
Ciao!
Hai possibilità di estrapolare il testo della query, e lanciarla dal tuo management studio?
In caso negativo, dovrai andare a recuperare lo statement con SQL Profiler, una server side trace o Extended Events.
In caso affermativo, potrai provare a lanciare la query, e cominciare ad analizzare il piano di esecuzione per determinare eventuali indici mancanti, statistiche non aggiornate, lacune nel database/data type design e perfino una scelta di operatori poco efficiente da parte del query optimizer (quando non viene chiaramente aiutato con nefandezze o dimenticanze...).
La cause per la regressione di performance non sono poi moltissime (mi capitò un caso con una tabella enorme e in costante movimento nella quale l'autoupdate delle statistiche non veniva triggerato), consiglio intanto di non riavviare ASSOLUTAMENTE i servizi di MSSQL perché anche se fosse benefico nei confronti di un singolo workload (da capire il perché), tale operazione è deleteria per tutto il resto del carico di lavoro ed azzera la profondità storica di alcune viste di sistema (DMV) che saranno interrogate dal povero DBA che fa troubleshooting (tu :D). In più togliamo al povero Database quei dati che aveva già caricato in memoria per evitare di leggere dal nostro lentissimo disco. Per questo, nella maggioranza dei casi, un riavvio dei servizi "peggiora" le performance, salvo rari casi (es. quando non limiti la max server memory di SQL e dopo mesi di uptime il server è alla canna del gas perché il nostro amato Database si è preso tutta la memoria disponibile...)
Imprescindibile quindi partire dal testo della query, e visualizzare il piano di esecuzione. Per questo, e per tutto il resto, SQL Server Management Studio/SQL Sentry (è free) e SQL Profiler ti sono sufficienti...magari se non vuoi postare il testo della query qui, potresti lanciarla attivando le statistiche I/O e copiare il risultato qui...
- Modificato Luca Bruno venerdì 25 novembre 2016 17:21
- Proposto come risposta Edoardo BenussiMVP, Moderator lunedì 28 novembre 2016 10:09
- Contrassegnato come risposta HunterNet79 mercoledì 7 dicembre 2016 09:57
-
Ciao!
AutoUpdate Statistic -> Quando è a true, SQL Server aggiorna le statistiche di una tabella sulla base di alcune condizioni prima di generare il piano di esecuzione. La query che fai sulla tabella quindi, avrà sempre le statistiche aggiornate (se è il caso che vengano aggiornate, chiaramente)...il costo dell'operazione di generazione statistiche lo paghi prima, ma hai il beneficio di piani di esecuzione ottimali. Quando è false, ti devi assolutamente ricordare di generare le statistiche nel tuo maintenance plan, o non lo farà nessuno...consigliato: true.
AutoUpdate Statistics Async -> Quando è a true, SQL Server preparerà il piano di esecuzione senza generare le statistiche. Tale compito verrà effettuato a posteriori, in un thread in background. Benefici: non paghi il costo di tale operazione, ma avrai piani di esecuzione potenzialmente non ottimali. Consigliato: false, finchè qualcuno ti dirà che tale costo ti sta causando problemi (forse in caso di database mostruosamente grandi, mai stato in una simile situazione...)
Broker Enable -> abilita SQL Server Broker, supporto nativo per code di distribuzione - permette ad alcuni processi opportunamente configurati di inviare o ricevere messaggi asincroni...non ha impatto diretto sul tuo problema.
--------------------------------------------------------------------------------------------------------------------------
Parallelamente a quanto Edoardo e Fabrizio hanno sottolineato, vorrei soffermarmi un momento sulla query.
SELECT * --> questo complica un pò le cose. Che tu sappia, l'applicazione deve necessariamente utilizzare tutti i campi della tabella, o sarebbe possibile restringere l'output?
TABLE SCAN --> Come avrai notato, SQL Server non ha molte opzioni in questo momento. La tabella è sprovvista di clustered index, quindi i dati non sono logicamente ordinati in nessun modo. E' come un elenco telefonico non ordinato, se hai bisogno di un numero te lo devi leggere tutto. Ci sono dei casi dove un table scan non rappresenta un problema, tipicamente tabelle molto piccole che non vengono messe in join con altre.
Viceversa, ipotizza un table scan su una tabella A con solo 1000 record in join con una tabella B contenente centinaia di migliaia\milioni di record. In tal caso la join potrebbe essere fortemente penalizzata dall'assenza di ordine e indici sulla tabella A...
Insomma...hai margini di manovra? La tabella è utilizzata in join con altre?
- Contrassegnato come risposta HunterNet79 mercoledì 7 dicembre 2016 09:47
Tutte le risposte
-
Ciao!
Hai possibilità di estrapolare il testo della query, e lanciarla dal tuo management studio?
In caso negativo, dovrai andare a recuperare lo statement con SQL Profiler, una server side trace o Extended Events.
In caso affermativo, potrai provare a lanciare la query, e cominciare ad analizzare il piano di esecuzione per determinare eventuali indici mancanti, statistiche non aggiornate, lacune nel database/data type design e perfino una scelta di operatori poco efficiente da parte del query optimizer (quando non viene chiaramente aiutato con nefandezze o dimenticanze...).
La cause per la regressione di performance non sono poi moltissime (mi capitò un caso con una tabella enorme e in costante movimento nella quale l'autoupdate delle statistiche non veniva triggerato), consiglio intanto di non riavviare ASSOLUTAMENTE i servizi di MSSQL perché anche se fosse benefico nei confronti di un singolo workload (da capire il perché), tale operazione è deleteria per tutto il resto del carico di lavoro ed azzera la profondità storica di alcune viste di sistema (DMV) che saranno interrogate dal povero DBA che fa troubleshooting (tu :D). In più togliamo al povero Database quei dati che aveva già caricato in memoria per evitare di leggere dal nostro lentissimo disco. Per questo, nella maggioranza dei casi, un riavvio dei servizi "peggiora" le performance, salvo rari casi (es. quando non limiti la max server memory di SQL e dopo mesi di uptime il server è alla canna del gas perché il nostro amato Database si è preso tutta la memoria disponibile...)
Imprescindibile quindi partire dal testo della query, e visualizzare il piano di esecuzione. Per questo, e per tutto il resto, SQL Server Management Studio/SQL Sentry (è free) e SQL Profiler ti sono sufficienti...magari se non vuoi postare il testo della query qui, potresti lanciarla attivando le statistiche I/O e copiare il risultato qui...
- Modificato Luca Bruno venerdì 25 novembre 2016 17:21
- Proposto come risposta Edoardo BenussiMVP, Moderator lunedì 28 novembre 2016 10:09
- Contrassegnato come risposta HunterNet79 mercoledì 7 dicembre 2016 09:57
-
vedi anche quanto suggerito qui sotto
Edoardo Benussi
Microsoft MVP - Enterprise Mobility
edo[at]mvps[dot]org -
Ciao , scusate il ritardo e grazie ad entrambi.
Ho ovviamente la possibilità di estrapolare il testo della query.
Resto un po' spazzato dalla mia "ignoranza" in merito:- Come è possibile analizzare il piano di esecuzione di una query ? Con il Profiler acceso o con il SQL Sentry (che ho appena scaricato ma mi pare di vedere "Gratis per 15gg" )?
Con il Managament Studio non saprei proprio come analizzare il piano di esecuzione!
- L'autoupdate delle statistiche deve essere impostato ?!?
Nella maggioranza dei casi io lo programmo con piano di manutenzione , una volta alla settimana....
- L'articolo suggerito da Edoardo è da considerasi solo se riscontro problematiche di utilizzo della memoria ?
Many Thanks !
Hunternet
- Come è possibile analizzare il piano di esecuzione di una query ? Con il Profiler acceso o con il SQL Sentry (che ho appena scaricato ma mi pare di vedere "Gratis per 15gg" )?
-
visto che nlel db non è cambiato niente ma è cambiata la macchina, avviare performance monitor e controllare cosa succede della memoria è una cosa che non costa molto.
prova, magari scopri altre cose che non ti hanno raccontato ;-)
Edoardo Benussi
Microsoft MVP - Enterprise Mobility
edo[at]mvps[dot]org -
Come è possibile analizzare il piano di esecuzione di una query ? Con il Profiler acceso o con il SQL Sentry (che ho appena scaricato ma mi pare di vedere "Gratis per 15gg" )?
Con il Managament Studio non saprei proprio come analizzare il piano di esecuzione!Per fortuna/purtroppo, anche qui vale la legge del "No Pain, no Gain". Analizzare un piano di esecuzione non è proprio un esercizio semplicissimo, soprattutto all'inizio. La soddisfazione che si trae però dall'investigazione e dalla risoluzione dei problemi di performance non è seconda a nessuno.
Per visualizzare il piano di esecuzione di una query (se stai usando SSMS), ti basta premere CTRL+M o aprire il menu Query, "Include Actual Execution Plan". Il piano di esecuzione apparirà in un nuovo tab, accanto a quello dei messaggi (Results|Messages|Execution Plan).
Il piano appare come una serie di flussi\pipelines (si legge da dx verso sx), attraverso i quali i dati vengono trasportati, trasformati, aggregati, ordinati, divisi da operatori che il query optimizer ha selezionato tra i disponibili, nel tentativo di ottenere la sequenza di operazioni più efficiente che possa portare al risultato richiesto (estrema sinistra del piano). Tale efficienza è esposta come "costo" dell'operazione in relazione al totale. In alcuni casi questo costo è uno dei campanelli di allarme che ti fa capire che forse un particolare passaggio sta "pesando" troppo sul totale, rappresentando un problema\collo di bottiglia.
Se provi a posizionare il cursore su di un operatore, troverai la sua relativa schermata di riepilogo, con una breve descrizione e una serie di utilissimi attributi che - a prima vista ti faranno venire di mal di testa - ma quando prenderai confidenza ti sapranno dire moltissimo su ciò che sta accadendo ai tuoi dati in quella particolare operazione; come per ogni cosa, l'esperienza aiuta moltissimo nell'interpretazione dei risultati, pertanto il mio consiglio è di provare ad analizzare qualche semplicissimo piano di esecuzione di una query prodotta da te, su una tabella che conosci (come cardinalità, copertura di indici, statistiche etc.).
Parti con una sola tabella, verifica quali operatori SQL Server ha selezionato e leggi due righe su quel particolare operatore: cosa rappresenta, cosa fa (i.e. l'operatore SORT li ordina. L'operatore FILTER li filtra. L'operatore Clustered Index Scan percorre un indice cluster...)
Non mi dilungo oltremodo, perché davvero - è difficile essere sintetici su un argomento così vasto...prova con semplici statement prima, ESPLORA il risultato e tenta di capire perché SQL Server ha avuto bisogno di aggregare, di ordinare, di percorrere, di calcolare...guarda il costo di ogni operatore. Se SQL Server ti consiglia un indice, NON CREARLO ;) , tenta di capire il perché te lo suggerisce, e se puoi restringere il numero di campi che richiedi in SELECT. Esamina anche le frecce che uniscono gli operatori...sono le famose pipeline dentro le quali viaggiano i tuoi dati. Guarda se SQL Server si aspetta di lavorare con un numero di righe simile a quello che effettivamente ha trovato. Cominciamo così, vediamo se ti viene l'appetito...
In chiusura, come non consigliarti il solito ebook gratuito...
- Modificato Luca Bruno martedì 29 novembre 2016 21:30
-
-
Sto facendo un po di verifiche ....
Intanto tra i due DB , sul vecchio e sul nuovo server (che sto mettendo in comparazione) ho scoperto le seguenti differenze nelle opzioni:
- AutoUpdate Statistic Asyncorono true nel vecchio, false nel nuovo
- Broker Enable true nel vecchio, false nel nuovoPoi, cercando di esplorare l'Execution Plan, ho scoperto alcune differenze nei "costi" (come ad esempio I/O).
Questo è il nuovo :
e questo è il vecchio:... .... ... idee !?!
Hunternet
-
i piani di esecuzione mi sembrano perfettamente identici. come ho già detto il problema sta nella configurazione della macchina nuova rispetto alla vecchia.
Edoardo Benussi
Microsoft MVP - Enterprise Mobility
edo[at]mvps[dot]org -
La cosa "strana" è che la macchina non risulta "lenta" in generale.
Sembrerebbe quasi un problema specifico di quella tabella: Query su altre tabelle sono velocissime (piu sul nuovo che sul vecchio) .
Il nuovo server è un WinSrv 2012 R2 con storage in Mirroring per SO e unico disco "DATI" con 6 dischi in RAID10 sul quale è virtualizzato il SrvSQL con HyperV . Sullo storage DATI c'è quindi la macchina virtuale con tutta la sua configurazione SQL, mdf e ldf .
Integro dicendo che il server ha 96 GB RAM e che la versione SQL , essendo una standard, ne utilizza "soltanto" 64 GB lasciando il resto al SO.
Hunternet
- Modificato HunterNet79 venerdì 2 dicembre 2016 11:03
-
Considera che anche se la macchina virtuale non sembra rallentata potrebbe non essere comunque configurata in maniera ottimale per SQL Server. Ad esempio l'array RAID10 è collegato in pass throught oppure hai utilizzato uno o più VHDX statici? Inoltre solitamente i dati di SQL Server dovrebbero trovarsi su spazi di storage differenti rispetto al sistema operativo.
Ti consiglio la lettura di questo documento:
-
Ciao!
AutoUpdate Statistic -> Quando è a true, SQL Server aggiorna le statistiche di una tabella sulla base di alcune condizioni prima di generare il piano di esecuzione. La query che fai sulla tabella quindi, avrà sempre le statistiche aggiornate (se è il caso che vengano aggiornate, chiaramente)...il costo dell'operazione di generazione statistiche lo paghi prima, ma hai il beneficio di piani di esecuzione ottimali. Quando è false, ti devi assolutamente ricordare di generare le statistiche nel tuo maintenance plan, o non lo farà nessuno...consigliato: true.
AutoUpdate Statistics Async -> Quando è a true, SQL Server preparerà il piano di esecuzione senza generare le statistiche. Tale compito verrà effettuato a posteriori, in un thread in background. Benefici: non paghi il costo di tale operazione, ma avrai piani di esecuzione potenzialmente non ottimali. Consigliato: false, finchè qualcuno ti dirà che tale costo ti sta causando problemi (forse in caso di database mostruosamente grandi, mai stato in una simile situazione...)
Broker Enable -> abilita SQL Server Broker, supporto nativo per code di distribuzione - permette ad alcuni processi opportunamente configurati di inviare o ricevere messaggi asincroni...non ha impatto diretto sul tuo problema.
--------------------------------------------------------------------------------------------------------------------------
Parallelamente a quanto Edoardo e Fabrizio hanno sottolineato, vorrei soffermarmi un momento sulla query.
SELECT * --> questo complica un pò le cose. Che tu sappia, l'applicazione deve necessariamente utilizzare tutti i campi della tabella, o sarebbe possibile restringere l'output?
TABLE SCAN --> Come avrai notato, SQL Server non ha molte opzioni in questo momento. La tabella è sprovvista di clustered index, quindi i dati non sono logicamente ordinati in nessun modo. E' come un elenco telefonico non ordinato, se hai bisogno di un numero te lo devi leggere tutto. Ci sono dei casi dove un table scan non rappresenta un problema, tipicamente tabelle molto piccole che non vengono messe in join con altre.
Viceversa, ipotizza un table scan su una tabella A con solo 1000 record in join con una tabella B contenente centinaia di migliaia\milioni di record. In tal caso la join potrebbe essere fortemente penalizzata dall'assenza di ordine e indici sulla tabella A...
Insomma...hai margini di manovra? La tabella è utilizzata in join con altre?
- Contrassegnato come risposta HunterNet79 mercoledì 7 dicembre 2016 09:47
-
ARIGRAZIE MILLE!
Solo una precisazione ulteriore: se come consigli , di base, imposto AutoUpdateStatistic a ON , posso evitare di fare l'aggiornamento delle statistiche nei piani di manutenzione oppure... meglio una volta in piu che una in meno! :-)
Fino ad oggi lasciavo questo valore a FALSE e lanciavo l'update ogni sera o settimana a seconda delle dimensioni/carico di lavoro del DB ... sto cercando di capire come ottimizzare anche tutte le future installazioni.
Riguardo invece le domanda sulla tabella....
Gli indici ci sono !! perchè mi dici che ne è sprovvista ? ;-)
GRAZIE
Hunternet
- Modificato HunterNet79 mercoledì 7 dicembre 2016 09:55
-
Io lo lascerei a true, però devi comunque prevedere di ricalcolare le statistiche, perchè SQL Server ricalcola in modo automatico le statistiche solo al raggiungimento di determinati thresholds. Questo potrebbe avvenire in modo "poco" frequente (che brutta frase).
Il tuo piano di maintenance, pertanto, non solo è utile, ma necessario al fine di ottenere il massimo della performance dal query optimizer ;)
Per quanto riguarda gli indici, probabilmente ce ne sono, ma nonclustered e non-covering, in questo caso, perchè l'operatore che viene scelto dal query optimizer è TABLE SCAN. Per soddisfare la tua query SQL Server non ha trovato nessun indice utile alla causa, e ne chiede uno a "gran voce" (impact 99.97%).
Attendo risposta per i miei quesiti :)
-