Warum würde SET ARITHABORT ON eine Abfrage dramatisch beschleunigen?

74

Die Abfrage ist eine einzelne Auswahl, die viele Gruppierungsebenen und Gesamtoperationen enthält. Mit SET ARITHABORT ON dauert es weniger als eine Sekunde, ansonsten dauert es einige Minuten. Wir haben dieses Verhalten auf SQL Server 2000 und 2008 gesehen.

Jonathan Allen
quelle

Antworten:

62

Ein bisschen veraltet, aber für alle, die hier ein ähnliches Problem haben ...

Ich hatte das gleiche problem Für mich stellte sich heraus, dass es sich um Parameterschnüffeln handelte, was ich zunächst nicht genug verstand, um mich darum zu kümmern. Ich habe ein 'set arithabort on' hinzugefügt, das das Problem behoben hat, aber dann ist es zurückgekommen. Dann las ich:

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

Es klärte sich alles auf. Da ich mit Linq to SQL gearbeitet habe und nur eingeschränkte Möglichkeiten zur Behebung des Problems hatte, habe ich schließlich einen Abfrageplan-Leitfaden (siehe Ende des Links) verwendet, um den gewünschten Abfrageplan zu erzwingen.


quelle
3
Mehr als sechs Jahre später ist der in dieser Antwort angegebene Link noch "lesenswert" ... und auch noch aktuell, die letzte Überarbeitung ist der Dezember '17.
Takrl
30

.NET-Anwendungen stellen eine Verbindung mit der Option her, die standardmäßig deaktiviert ist, in Management Studio jedoch standardmäßig aktiviert ist. Das Ergebnis ist, dass der Server tatsächlich zwei separate Ausführungspläne für die meisten / alle Prozeduren zwischenspeichert. Dies wirkt sich darauf aus, wie der Server numerische Berechnungen durchführt, und daher können je nach Vorgang sehr unterschiedliche Ergebnisse erzielt werden. Dies ist wirklich nur eine von zwei üblichen Möglichkeiten, wie ein Proc einen schrecklichen Ausführungsplan erhalten kann, der andere ist das Parameter-Sniffing.

Schauen Sie sich https://web.archive.org/web/20150315031719/http://sqladvice.com/blogs/gstark/archive/2008/02/12/Arithabort-Option-Effects-Stored-Procedure-Performance an. aspx für ein wenig mehr Diskussion darüber.

Ben Hoffman
quelle
Ich stimme der Hälfte dieser Antwort zu. Bin allerdings sehr skeptisch gegenüber dem numerischen Rechenanspruch!
Martin Smith
2
@Martin: Ich glaube ich war unklar. Ich habe nur gesagt, dass mit ARITHABORT ON SQL Server bei div / 0- oder arithmetischen Überlauffehlern einen Fehler ausgibt. Wenn es ausgeschaltet ist, geht es weiter und kann aus irgendeinem Grund alle möglichen schrecklichen Probleme verursachen.
@Ben - Ja, tut mir leid, ich wollte Ihre Antwort nicht besonders angreifen. Ich habe nur darauf hingewiesen, dass es sehr einfach wäre, eine SETOption zu ändern, um einen besseren Plan zu erhalten, und dies fälschlicherweise als die Option selbst zu diagnostizieren, die schuld ist. Ich bin nicht überzeugt, dass der Typ in Ihrem Link dies nicht getan hat.
Martin Smith
@Martin - Kein Problem, ich hätte nicht gedacht, dass du mich angreifst. Die andere Diskussion, die ich verbunden habe, könnte etwas unklar sein. Ich habe nur versucht, Belege zu liefern.
@ Martin Rückblickend glaube ich, dass Sie richtig sind.
21

Ich würde argumentieren, dass dies mit ziemlicher Sicherheit Parameter-Sniffing war.

Es wird häufig angegeben, dass SET OPTIONSsich dies auf die Leistung auswirken kann, es ist jedoch noch keine einzige maßgebliche Quelle für diese Behauptung vorhanden, mit Ausnahme des Falls, dass Sie indizierte Ansichten / persistierte berechnete Spalten verwenden.

In diesem Fall (für SQL2005 + und sofern sich Ihre Datenbank nicht im SQL2000-Kompatibilitätsmodus befindet ). Wenn Sie beides haben ARITHABORTund ANSI_WARNINGS OFFdann feststellen, dass der Index nicht verwendet wird, wird möglicherweise eher ein Scan als der gewünschte Suchvorgang ausgeführt (und ein gewisser Overhead, da das dauerhafte Berechnungsergebnis nicht verwendet werden kann). ADO.NET scheint standardmäßig ANSI_WARNINGS ONeinen kurzen Test zu haben, den ich gerade durchgeführt habe.

Die Behauptung in Bens Antwort, dass "die Art und Weise, wie der Server numerische Berechnungen durchführt", einem Ergebnis Minuten hinzufügen kann, das sonst weniger als eine Sekunde dauern würde, scheint mir einfach nicht glaubwürdig. Ich denke, was dazu neigt, ist, dass bei der Untersuchung eines Performance-Performance-Problems der Profiler verwendet wird, um die störende Abfrage zu identifizieren. Dies wird in Management Studio eingefügt und ausgeführt und liefert sofort Ergebnisse. Der einzige offensichtliche Unterschied zwischen den Anschlüssen ist die ARITH_ABORTOption.

Ein schneller Test in einem Management Studio-Fenster zeigt, dass, wenn SET ARITHABORT OFFaktiviert und die Abfrage ausgeführt wird, das Leistungsproblem erneut auftritt und der Fall anscheinend geschlossen ist. In der Tat scheint dies die im Gregg Stark- Link verwendete Fehlerbehebungsmethode zu sein .

Dies ignoriert jedoch die Tatsache, dass Sie mit dieser Option den exakt gleichen fehlerhaften Plan aus dem Cache erhalten können .

Diese Planwiederverwendung kann auch dann auftreten, wenn Sie als ein anderer Benutzer angemeldet sind, als von der Anwendungsverbindung verwendet wird.

Ich habe dies getestet, indem ich eine Testabfrage zuerst von einer Webanwendung aus SET ARITHABORT OFFund dann von Management Studio mit ausgeführt habe. Dabei konnte ich feststellen, dass die Anzahl der Verwendungszwecke von der folgenden Abfrage abweicht.

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) 

Damit diese Freigabe von Plänen tatsächlich erfolgt, müssen alle Plan-Cache-Schlüssel gleich sein. Neben arithabortsich die ausführenden Benutzer benötigen die gleiche Standardschema einige andere Beispiele sind (wenn die Abfrage auf implizite Namensauflösung beruht) und die Verbindungen müssen den gleichen languageSatz.

Eine ausführlichere Liste der Plan-Cache-Schlüssel finden Sie hier

Martin Smith
quelle
12

Ich weiß, dass ich zu spät zu dieser Party komme, aber für zukünftige Besucher ist Martin genau richtig. Wir hatten das gleiche Problem: Ein SP lief für .NET-Clients sehr langsam, während er für SSMS blitzschnell war. Bei der Untersuchung und Lösung des Problems haben wir die systematischen Tests durchgeführt, nach denen Kenny Evitt in seinem Kommentar zu Martins Frage fragt.

Unter Verwendung einer Variante von Martins Abfrage habe ich nach dem SP im Prozedurcache gesucht und zwei von ihnen gefunden. Wenn man sich die Pläne ansieht, war es tatsächlich so, dass man ARITHABORT AN und ARITHABORT AUS hatte. Die ARITHABORT OFF-Version hatte eine Indexsuche, während die ARITHABORT ON-Version eine Indexsuche für dieselbe Ausgabe verwendete. Angesichts der beteiligten Parameter hätte die Indexsuche eine Suche in zig Millionen Datensätzen für die Ausgabe erforderlich gemacht.

Ich löschte die beiden Prozeduren aus dem Cache und ließ den .NET-Client den SP erneut ausführen, wobei dieselben Parameter verwendet wurden (die einen großen Datumsbereich für einen Kunden mit vielen Aktivitäten aufwiesen). Der SP kehrte sofort zurück. Der zwischengespeicherte Plan verwendete den gleichen Index-Scan wie zuvor im ARITHABORT ON-Plan, diesmal jedoch für ARITHABORT OFF. Wir haben den SP mit denselben Parametern in SSMS ausgeführt und sofort wieder Ergebnisse erzielt. Jetzt haben wir gesehen, dass ein zweiter Plan für ARITHABORT ON mit dem Index-Scan zwischengespeichert wurde.

Wir haben dann den Cache geleert, den SP in SSMS mit einem engen Datumsbereich ausgeführt und ein sofortiges Ergebnis erhalten. Wir stellten fest, dass der resultierende zwischengespeicherte Plan eine Indexsuche aufwies, da dieselbe Ausgabe zuvor mit einem Scan behandelt wurde (der auch im ursprünglichen Plan mit ARITHABORT OFF gesucht wurde). Erneut von SSMS aus führten wir den SP aus, diesmal mit demselben breiten Datumsbereich, und sahen die gleiche schreckliche Leistung, die wir in der ursprünglichen .NET-Anforderung hatten.

Kurz gesagt, die Ungleichheit hatte nichts mit dem tatsächlichen Wert von ARITHABORT zu tun - mit dem Ein- oder Ausschalten konnten wir von jedem Client eine akzeptable oder schreckliche Leistung erzielen: Alles, was zählte, waren die Parameterwerte, die beim Kompilieren und Zwischenspeichern des Plans verwendet wurden.

Während MSDN angibt, dass ARITHABORT OFF sich negativ auf die Abfrageoptimierung auswirken kann, bestätigen unsere Tests, dass Martin korrekt ist - die Ursache war Parameter-Sniffing und der resultierende Plan war nicht für alle Parameterbereiche optimal.

mdoyle
quelle
1
Ich frage mich, was dieser Satz Setting ARITHABORT to OFF can negatively impact query optimization leading to performance issues.bedeutet. Ob es sich nur um die Unfähigkeit handelt, Indizes für berechnete Spalten und Ansichten zu verwenden (sofern diese ANSI_WARNINGSOption ebenfalls deaktiviert ist) oder ob sie tatsächlich einen anderen Effekt haben.
Martin Smith
Ich bin mir nicht sicher. Ich frage mich, ob es einfach so ist, dass jemand bei MSDN in eine ähnliche Situation geriet, ARTIHABORT auf ON stellte, die Leistungsverbesserung sah und zu denselben Schlussfolgerungen kam, die andere gezogen haben. Was indizierte Ansichten und berechnete Spalten angeht, bin ich unklar. An einem Punkt heißt es, dass die SET-Optionen bestimmte Werte haben müssen, wenn eine INSERT-, UPDATE- oder DELETE-Operation darin gespeicherte Datenwerte ändert. An anderer Stelle wird angegeben, dass das Optimierungsprogramm Indizes für "alle Abfragen" ignoriert, die auf die indizierte Ansicht oder die berechnete Spalte verweisen. Stimmt beides, oder handelt es sich tatsächlich um "Daten, die eine Abfrage ändern"?
Mdoyle
1

Hatte gerade dieses Problem. Wie hier bereits erwähnt, liegt die Ursache in mehreren Abfrageplänen, von denen einer nicht optimal ist. Ich wollte nur überprüfen, ob ARITHABORT das Problem tatsächlich selbst verursachen kann (da die Abfrage, mit der ich Probleme hatte, keine Parameter hatte, wodurch das Parameter-Sniffing aus der Gleichung entfernt wird).

Alan D. Nelson
quelle
1

Dies erinnert mich genau an das Problem, das ich in den Tagen von SQL Server 2008 hatte. In unserem Fall stellte sich plötzlich heraus, dass ein SQL-Job plötzlich langsamer wurde (normalerweise einige Sekunden und jetzt mehr als 9 Minuten), der Job muss auf einen Verbindungsserver zugreifen, wir haben im Jobschritt die Einstellung ARITHABORT aktiviert, und es schien das Problem zu sein wurde für ein paar Tage gelöst und kehrte dann zurück.

Wir haben später ein Ticket mit MS-Support eröffnet, und anfangs konnten sie es auch nicht herausfinden. Das Ticket wurde an ein sehr erfahrenes PFE-Team weitergeleitet, und zwei Support-PFEs versuchten, dieses Problem zu lösen.

Der letzte Grund ist, dass der Benutzer-Berechtigungsnachweis (zum Ausführen des Auftragsschritts) nicht auf die Statistiken der zugrunde liegenden Tabellen (auf der Seite des Verbindungsservers) zugreifen kann und daher der Ausführungsplan nicht optimiert wird.

Im Detail hat der Benutzer keine Berechtigung für DBCC SHOW_STATISTICS (obwohl der Benutzer aus der Tabelle AUSWÄHLEN kann). Laut MSDN , diese Berechtigung Regel nach SQL 2012 SP1 geändert

Berechtigungen für SQL Server und SQL-Datenbank

Um das Statistikobjekt anzuzeigen, muss der Benutzer Eigentümer der Tabelle sein oder ein Mitglied der festen Serverrolle sysadmin, der festen Datenbankrolle db_owner oder der festen Datenbankrolle db_ddladmin sein.

SQL Server 2012 SP1 ändert die Berechtigungseinschränkungen und ermöglicht Benutzern mit SELECT-Berechtigung die Verwendung dieses Befehls. Beachten Sie, dass die folgenden Anforderungen erfüllt sein müssen, damit SELECT-Berechtigungen zum Ausführen des Befehls ausreichen:

Um dieses Problem zu überprüfen, müssen wir nur den Profiler auf der Verbindungsserver-Instanz ausführen und einige Ereignisse im Abschnitt "Fehler und Warnungen" aktivieren, wie unten gezeigt.

Bildbeschreibung hier eingeben

Hoffe, diese Erfahrung kann der Community irgendwie helfen.

jyao
quelle