Perché SET ARITHABORT ON velocizzerebbe notevolmente una query?


75

La query è una singola selezione che contiene molti livelli di raggruppamento e operazioni aggregate. Con SET ARITHABORT ON è necessario meno di un secondo, altrimenti sono necessari diversi minuti. Abbiamo riscontrato questo comportamento su SQL Server 2000 e 2008.

Risposte:


62

Un po 'datato, ma per chiunque finisca qui con un problema simile ...

Ho avuto lo stesso problema. Per me si è rivelato essere un parametro sniffing, che all'inizio non ho capito abbastanza di cui preoccuparmi. Ho aggiunto un 'set arithabort su' che ha risolto il problema, ma poi è tornato. Poi ho letto:

http://www.sommarskog.se/query-plan-mysteries.html

Ha chiarito tutto. Poiché stavo usando Linq to SQL e avevo opzioni limitate per risolvere il problema, ho finito per usare una guida al piano di query (vedi fine del collegamento) per forzare il piano di query che volevo.


3
Più di sei anni dopo, il link fornito in questa risposta è ancora "lettura obbligatoria" ... ed è ancora attuale, l'ultima revisione risale al dicembre '17.
Takrl

30

Le applicazioni .NET si connettono con l'opzione disabilitata per impostazione predefinita, ma è abilitata per impostazione predefinita in Management Studio. Il risultato è che il server memorizza nella cache 2 piani di esecuzione separati per la maggior parte / tutte le procedure. Ciò influisce sul modo in cui il server esegue calcoli numerici e come tale è possibile ottenere risultati notevolmente diversi a seconda della procedura. Questo è davvero solo uno dei 2 modi comuni in cui un proc può ricevere un terribile piano di esecuzione, l'altro è l'annusamento dei parametri.

Dai un'occhiata a https://web.archive.org/web/20150315031719/http://sqladvice.com/blogs/gstark/archive/2008/02/12/Arithabort-Option-Effects-Stored-Procedure-Performance. aspx per un po 'più di discussione al riguardo.


Sono d'accordo con metà di questa risposta. Sono molto scettico sull'affermazione del calcolo numerico!
Martin Smith,

2
@Martin: penso di non essere chiaro. Stavo solo dicendo che ARITHABORT ON rende SQL Server errore su qualsiasi div / 0 o errore di overflow aritmetico. Quando è spento continua e per qualsiasi motivo può causare tutti i tipi di problemi orribili.

@Ben - Sì, scusami, non volevo attaccare in modo particolare la tua risposta, stavo solo sottolineando che sarebbe molto facile cambiare SETun'opzione per ottenere un piano migliore e diagnosticare erroneamente questa come l'opzione stessa che è in errore. Non sono convinto che il ragazzo nel tuo link non l'abbia fatto.
Martin Smith,

@Martin - Non è un problema, non pensavo che mi stessi attaccando. L'altra discussione che ho collegato potrebbe essere un po 'poco chiara. Stavo solo cercando di fornire prove a sostegno.

@Martin In retrospettiva credo che tu abbia ragione.

21

Direi che si trattava quasi sicuramente di uno sniffing dei parametri.

Si afferma spesso che SET OPTIONSpuò influire sulle prestazioni in questo modo, ma devo ancora vedere un'unica fonte autorevole per questa affermazione, tranne nel caso in cui si utilizzino visualizzazioni indicizzate / colonne calcolate persistenti.

In questo caso (per SQL2005 + e, a meno che il database non sia in modalità di compatibilità SQL2000 ). Se hai entrambi ARITHABORTe ANSI_WARNINGS OFFallora troverai che l'indice non viene utilizzato, quindi potresti avere una scansione piuttosto che la ricerca desiderata (e un certo sovraccarico poiché il risultato del calcolo persistente non può essere usato). ADO.NET sembra avere come impostazione predefinita ANSI_WARNINGS ONun test rapido che ho appena fatto.

L'affermazione nella risposta di Ben secondo cui "il modo in cui il server esegue calcoli numerici" può aggiungere minuti a un risultato che altrimenti richiederebbe meno di un secondo non mi sembra credibile. Penso che ciò che tende a succedere sia che, quando si studia un problema di prestazioni, Profiler viene utilizzato per identificare la query offensiva. Questo viene incollato in Management Studio ed eseguito e restituisce immediatamente i risultati. L'unica differenza apparente tra le connessioni è l' ARITH_ABORTopzione.

Un test rapido in una finestra di Management Studio mostra che quando SET ARITHABORT OFFviene attivato e viene eseguita la query, il problema di prestazioni si ripresenta in modo che apparentemente venga chiuso. In effetti, questa sembra essere la metodologia di risoluzione dei problemi utilizzata nel collegamento Gregg Stark .

Tuttavia, ciò ignora il fatto che con quell'opzione impostata è possibile ottenere esattamente lo stesso piano errato dalla cache .

Il riutilizzo di questo piano può verificarsi anche se si è effettuato l'accesso come utente diverso da quello utilizzato dalla connessione dell'applicazione.

Ho provato questo eseguendo prima una query di prova da un'applicazione Web e poi da Management Studio con SET ARITHABORT OFFe ho potuto vedere gli account utente salire dalla query di seguito.

SELECT usecounts, cacheobjtype, objtype, text ,query_plan
FROM sys.dm_exec_cached_plans 
CROSS APPLY sys.dm_exec_sql_text(plan_handle) 
CROSS APPLY sys.dm_exec_query_plan(plan_handle) 

Affinché questa condivisione dei piani pf avvenga effettivamente, tutte le chiavi della cache del piano devono essere uguali. Oltre a se arithabortstesso, alcuni altri esempi sono gli utenti che eseguono lo stesso schema predefinito (se la query si basa sulla risoluzione implicita del nome) e le connessioni necessitano dello stesso languageset.

Un elenco più completo di chiavi della cache del piano qui


13

So di essere in ritardo a questa festa, ma per i futuri visitatori, Martin ha esattamente ragione. Abbiamo riscontrato questo stesso problema: un SP funzionava molto lentamente per i client .NET, mentre era velocissimo per SSMS. Nell'esplorazione e nella risoluzione del problema, abbiamo svolto i test sistematici di cui Kenny Evitt fa domande nel suo commento alla domanda di Martin.

Usando una variante della query di Martin, ho cercato l'SP nella cache delle procedure e ne ho trovate due. Guardando i piani, era in effetti il ​​caso di uno con ARITHABORT ON e di uno con ARITHABORT OFF. La versione ARITHABORT OFF aveva una ricerca dell'indice mentre la versione ARITHABORT ON utilizzava una scansione dell'indice per lo stesso output. Dati i parametri coinvolti, la ricerca dell'indice avrebbe richiesto una ricerca su decine di milioni di record per l'output.

Ho cancellato le due procedure dalla cache e il client .NET ha eseguito di nuovo l'SP, utilizzando gli stessi parametri (che presentavano un ampio intervallo di date per un cliente con molte attività). L'SP è tornato all'istante. Il piano memorizzato nella cache utilizzava la stessa scansione dell'indice precedentemente inclusa nel piano ARITHABORT ON, ma questa volta il piano era per ARITHABORT OFF. Abbiamo eseguito l'SP con gli stessi parametri in SSMS e abbiamo ottenuto risultati immediatamente. Ora abbiamo visto che un secondo piano era stato memorizzato nella cache, per ARITHABORT ON, con la scansione dell'indice.

Abbiamo quindi svuotato la cache, eseguito l'SP in SSMS con un intervallo di date limitato e ottenuto un risultato immediato. Abbiamo scoperto che il piano cache risultante aveva una ricerca di indice, poiché lo stesso output era precedentemente gestito con una scansione (che era anche una ricerca nel piano originale con ARITHABORT OFF). Ancora una volta da SSMS, abbiamo eseguito SP, questa volta con lo stesso ampio intervallo di date, e abbiamo visto le stesse terribili prestazioni che avevamo nella richiesta .NET originale.

In breve, la disparità non aveva nulla a che fare con il valore reale di ARITHABORT - con esso acceso o spento, da entrambi i client, potevamo ottenere prestazioni accettabili o terribili: tutto ciò che contava erano i valori dei parametri utilizzati nella compilazione e nella memorizzazione nella cache del piano.

Mentre MSDN indica che ARITHABORT OFF stesso può avere un impatto negativo sull'ottimizzazione della query, i nostri test confermano che Martin è corretto: la causa era lo sniffing dei parametri e il piano risultante non era ottimale per tutti gli intervalli di parametri.


1
Mi chiedo cosa Setting ARITHABORT to OFF can negatively impact query optimization leading to performance issues.significhi quella frase . Sia che stiano solo parlando dell'incapacità di utilizzare gli indici su colonne e viste calcolate (se ANSI_WARNINGSè anche disattivato) o se ha effettivamente qualche altro effetto.
Martin Smith,

Non ne sono sicuro. Mi chiedo se è semplicemente il caso che qualcuno di MSDN si sia imbattuto in una situazione simile, abbia impostato ARTIHABORT su ON, visto il miglioramento delle prestazioni e passato alle stesse conclusioni che altri hanno. Per quanto riguarda le viste indicizzate e le colonne calcolate, non sono chiaro. Ad un certo punto afferma che le opzioni SET devono avere valori specifici se un'operazione INSERT, UPDATE o DELETE modifica i valori dei dati memorizzati al loro interno. Altrove affermano che l'ottimizzatore ignorerà gli indici per "qualsiasi query" che fa riferimento a detta vista indicizzata o colonna calcolata. Sono entrambi veri o è davvero "una query che modifica i dati"?
mdoyle,

1

Ho appena avuto questo problema. Come dicevano le persone qui, la causa principale sono molteplici piani di query, uno dei quali non è ottimale. Volevo solo verificare che ARITHABORT potesse effettivamente causare il problema da solo (poiché la query con cui avevo problemi non aveva parametri, il che toglie il parametro dall'annullamento dell'equazione).


1

Questo mi ricorda esattamente lo stesso problema che ho riscontrato in SQL Server 2008 giorni. Nel nostro caso, abbiamo trovato improvvisamente un lavoro sql rallentato improvvisamente (di solito pochi secondi e ora 9+ minuti), il lavoro deve accedere a un server collegato, abbiamo aggiunto impostare ARITHABORT nel passaggio del lavoro e sembrava che il problema è stato risolto per alcuni giorni e poi restituito.

Successivamente abbiamo aperto un ticket con il supporto di MS, e inizialmente non sono stati in grado di scoprirlo, e il ticket è stato inoltrato a un team PFE molto anziano, e due PFE di supporto hanno cercato di capire questo problema.

L'ultimo motivo è che le credenziali dell'utente (per eseguire la fase del lavoro) non possono accedere alle statistiche delle tabelle sottostanti (sul lato del server collegato) e quindi il piano di esecuzione non è ottimizzato.

Nel dettaglio, l'utente non dispone dell'autorizzazione per DBCC SHOW_STATISTICS (sebbene l'utente possa SELEZIONARE dalla tabella). Secondo MSDN , questa regola di autorizzazione viene modificata dopo sql 2012 SP1

Autorizzazioni per SQL Server e database SQL

Per visualizzare l'oggetto statistico, l'utente deve possedere la tabella oppure l'utente deve essere un membro del ruolo predefinito del server sysadmin, del ruolo predefinito del database db_owner o del ruolo predefinito del database db_ddladmin.

SQL Server 2012 SP1 modifica le restrizioni di autorizzazione e consente agli utenti con autorizzazione SELECT di utilizzare questo comando. Si noti che esistono i seguenti requisiti affinché le autorizzazioni SELECT siano sufficienti per eseguire il comando:

Per verificare questo problema, è sufficiente eseguire il profiler sull'istanza lato server collegata e attivare alcuni eventi nella sezione "Errori e avvisi" come mostrato di seguito.

inserisci qui la descrizione dell'immagine

Spero che questa esperienza possa aiutare la comunità in qualche modo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.