risposta-alla-domanda-sullo-sviluppo-web-bd.com

La query si interrompe quando viene eseguita dal Web, ma super veloce quando viene eseguita da SSMS

Sto cercando di eseguire il debug dell'origine di un timeout SQL in un'applicazione Web che mantengo. Ho il codice sorgente del codice C # dietro, quindi so esattamente quale codice è in esecuzione. Ho eseguito il debug dell'applicazione fino alla riga che esegue il codice SQL scaduto e guardo la query in esecuzione nel profiler SQL. 

Quando questa query viene eseguita dal Web, viene interrotta dopo 30 secondi. Tuttavia, quando taglio/incolla la query esattamente come presentata in Profiler, e la inserisco in SSMS ed eseguo, ritorna quasi istantaneamente. Ho tracciato il problema che ARITHABORT è stato impostato su OFF nella connessione utilizzata dal web (ovvero, se ARITHABORT viene disattivato nella sessione SSMS, viene eseguito per un lungo periodo di tempo e, se lo riaccendo, viene eseguito molto velocemente). Comunque, leggendo la descrizione di ARITHABORT, non sembra applicarsi ... Sto solo facendo un semplice SELECT, e non c'è NESSUNA aritmetica eseguita ... solo un singolo INNER JOIN con una condizione WHERE:

Perché ARITHABORT OFF dovrebbe causare questo comportamento in questo contesto ?? C'è un modo per modificare l'impostazione ARITHABORT per quella connessione da SSMS? Sto usando SQL Server 2008.

39
Michael Bray

Quindi il tuo codice C # sta inviando una query SQL ad hoc a SQL Server, usando quale metodo? Hai preso in considerazione l'utilizzo di una stored procedure? Ciò probabilmente garantirebbe le stesse prestazioni (almeno nel motore) indipendentemente da chi lo avesse chiamato. 

Perché? L'impostazione ARITHABORT è una delle cose che l'ottimizzatore considera quando determina come eseguire la query (in particolare, per la corrispondenza del piano). È possibile che il piano nella cache abbia la stessa impostazione di SSMS, quindi usa il piano memorizzato nella cache, ma con l'impostazione opposta il codice C # sta forzando una ricompilazione (o forse stai colpendo veramenteCATTIVOpiano nella cache), che può certamente danneggiare le prestazioni in molti casi. 

Se stai già chiamando una procedura memorizzata (non hai inserito la tua query, anche se penso che intendevi farlo), puoi provare ad aggiungere OPTION (RECOMPILE) alla query (o alle query) incriminata nella stored procedure. Ciò significa che tali istruzioni verranno sempre ricompilate, ma potrebbe impedire l'utilizzo del piano errato che si sta riscontrando. Un'altra opzione è assicurarsi che quando la procedura memorizzata è compilata, il batch venga eseguito con SET ARITHABORT ON.

Infine, sembra che tu stia chiedendo come modificare l'impostazione ARITHABORT in SSMS. Penso che quello che volevi chiedere è come forzare l'impostazione ARITHABORT nel tuo codice. Se decidi di continuare a inviare SQL ad hoc dall'app C #, ovviamente puoi inviare un comando come testo con più istruzioni separate da punti e virgola, ad esempio:

SET ARITHABORT ON; SELECT ...

Per maggiori informazioni sul perché questo problema si verifica, vedere l'ottimo articolo di Erland Sommarskog:

38
Aaron Bertrand

Questa risposta include un modo per risolvere questo problema:

Eseguendo i seguenti comandi come amministratore sul database, tutte le query vengono eseguite come previsto indipendentemente dall'impostazione ARITHABORT.

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

Aggiornare

Sembra che molte persone finiscono per avere questo problema si verificano molto raramente, e la tecnica di cui sopra è una soluzione decente una volta. Ma se una query specifica presenta questo problema più di una volta, una soluzione più a lungo termine a questo problema sarebbe quella di utilizzare suggerimenti di query come OPTIMIZE FOR e OPTION(Recompile), come descritto in questo articolo .

12

Ho avuto questo problema molte volte in passato, ma se si dispone di una stored procedure con lo stesso problema, l'eliminazione e la ricreazione del proc memorizzato risolveranno il problema.

Si chiama parametro sniffing. È necessario localizzare sempre i parametri nel proc memorizzato per evitare questo problema in futuro.

Capisco che questo potrebbe non essere ciò che vuole il manifesto originale, ma potrebbe aiutare qualcuno con lo stesso problema.

3
Novice in.NET

Se si utilizza Entity Framework, è necessario tenere presente che i parametri di query per i valori stringa vengono inviati al database come nvarchar, se la colonna del database da confrontare è un varchar, in base alle regole di confronto potrebbe richiedere una "CONVERSIONE IMPLICIT" che evita gli indici. 

Finalmente trovato grazie a questo articolo: https://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-cause-index-scans/

1
edumen

Ho avuto lo stesso problema ed è stato risolto eseguendo la procedura "WITH RECOMPILE". Puoi anche provare a usare lo sniffing dei parametri. Il mio problema era correlato alla cache SQL. 

0
Manmeet

Se è possibile modificare il codice per correggere lo sniffing dei parametri, ottimizzare per il suggerimento sconosciuto è la scelta migliore. Se non è possibile modificare il codice, l'opzione migliore è exec sp_recompile 'nome di proc' che imporrà solo un processo memorizzato per ottenere un nuovo piano di esecuzione. Eliminare e ricreare un proc avrebbe un effetto simile ma potrebbe causare errori se qualcuno tenta di eseguire il proc finché non viene rilasciato. DBCC FREEPROCCACHE elimina tutti i piani memorizzati nella cache che possono distruggere lo scompiglio del sistema fino a causare numerosi timeout in un ambiente di produzione di transazioni pesanti. L'impostazione di arithabort non è una soluzione al problema, ma è uno strumento utile per scoprire se il problema dello sniffing dei parametri.

0
N. Rhoades

Ho lo stesso problema quando provo a chiamare SP da SMSS ci sono voluti 2 secondi, mentre da webapp (ASP.NET) ci sono voluti circa 3 minuti.

Ho provato tutte le soluzioni suggerite sp_recompile, DBCC FREEPROCCACHE e DBCC DROPCLEANBUFFERS ma nulla ha risolto il mio problema, ma quando ho provato il parametro sniffing ha funzionato e ha funzionato bene. 

0
Karim Tawfik