it-swarm.com.de

Warum sollte SET ARITHABORT ON eine Abfrage drastisch beschleunigen?

Die Abfrage ist eine einzelne Auswahl, die viele Gruppierungsebenen und Aggragate-Operationen enthält. Wenn SET ARITHABORT ON aktiviert ist, dauert es weniger als eine Sekunde, andernfalls dauert es einige Minuten. Wir haben dieses Verhalten unter SQL Server 2000 und 2008 gesehen.

79
Jonathan Allen

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 Parameter-Sniffing handelte, was ich zunächst nicht genug verstand, um mich darum zu kümmern. Ich habe einen 'arithabort gesetzt' hinzugefügt, der das Problem behoben hat, aber dann kam er zurück. Dann las ich:

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

Es klärte alles auf. Da ich Linq to SQL verwendete und nur begrenzte Optionen zur Behebung des Problems hatte, verwendete ich schließlich einen Abfrageplan-Leitfaden (siehe Ende des Links), um den gewünschten Abfrageplan zu erzwingen.

63
Jason

.NET-Anwendungen stellen eine Verbindung mit der standardmäßig deaktivierten Option her, die jedoch in Management Studio standardmäßig aktiviert ist. Das Ergebnis ist, dass der Server tatsächlich 2 separate Ausführungspläne für die meisten/alle Prozeduren zwischenspeichert. Dies wirkt sich darauf aus, wie der Server numerische Berechnungen durchführt. Daher können Sie je nach Verfahren sehr unterschiedliche Ergebnisse erzielen. Dies ist wirklich nur eine von zwei üblichen Möglichkeiten, wie ein Proc einen schrecklichen Ausführungsplan erhalten kann, die 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 an -Effects-Stored-Procedure-Performance.aspx für ein wenig mehr Diskussion darüber.

30
Ben Hoffman

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

Es wird häufig angegeben, dass SET OPTIONS Die Leistung auf diese Weise beeinflussen kann, aber ich habe noch keine einzige maßgebliche Quelle für diesen Anspruch gefunden, außer in dem Fall, in dem Sie indizierte Ansichten/persistierte berechnete Spalten verwenden.

In diesem Fall (für SQL2005 + und es sei denn, Ihre Datenbank befindet sich im SQL2000-Kompatibilitätsmodus ). Wenn Sie sowohl ARITHABORT als auch ANSI_WARNINGSOFF haben, wird der Index nicht verwendet, sodass möglicherweise eher ein Scan als die gewünschte Suche durchgeführt wird (und ein gewisser Overhead als dauerhafte Berechnung) Ergebnis kann nicht verwendet werden). ADO.NET scheint standardmäßig ANSI_WARNINGS ON Aus einem Schnelltest 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 Leistungsleistungsproblems Profiler verwendet wird, um die fehlerhafte Abfrage zu identifizieren. Dies wird in das Management Studio eingefügt und ausgeführt und liefert sofort Ergebnisse. Der einzige offensichtliche Unterschied zwischen Verbindungen ist die Option ARITH_ABORT.

Ein schneller Test in einem Management Studio-Fenster zeigt, dass beim Aktivieren von SET ARITHABORT OFF Und Ausführen der Abfrage das Leistungsproblem erneut auftritt, sodass der Fall anscheinend geschlossen ist. In der Tat scheint dies die Fehlerbehebungsmethode zu sein, die im Link Gregg Stark verwendet wird.

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

Diese Wiederverwendung des Plans kann auch dann erfolgen, wenn Sie als anderer Benutzer als die von der Anwendungsverbindung verwendete angemeldet sind.

Ich habe dies getestet, indem ich zuerst eine Testabfrage aus einer Webanwendung und dann aus dem Management Studio mit SET ARITHABORT OFF Ausgeführt habe. In der folgenden Abfrage konnte ich feststellen, dass die Benutzerzahlen steigen.

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 gemeinsame Nutzung von Plänen tatsächlich stattfinden kann, müssen alle Plan-Cache-Schlüssel gleich sein. Neben arithabort selbst sind einige andere Beispiele, dass die ausführenden Benutzer dasselbe Standardschema benötigen (wenn die Abfrage auf einer impliziten Namensauflösung beruht) und die Verbindungen denselben Satz language benötigen.

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

21
Martin Smith

Ich weiß, dass ich zu spät zu dieser Party komme, aber für zukünftige Besucher ist Martin genau richtig. Wir sind auf dasselbe Problem gestoßen - ein SP lief für .NET-Clients sehr langsam, während es für SSMS sehr schnell lief. Bei der Untersuchung und Lösung des Problems haben wir die systematischen Tests durchgeführt, die Kenny durchgeführt hat Evitt fragt in seinem Kommentar zu Martins Frage.

Unter Verwendung einer Variante von Martins Abfrage suchte ich im Prozedur-Cache nach SP und fand zwei davon). Bei den Plänen war es tatsächlich so, dass einer ARITHABORT ON hatte und einer hatte ARITHABORT OFF. Die ARITHABORT OFF-Version hatte eine Indexsuche, während die ARITHABORT ON-Version einen Indexscan für dieselbe Ausgabe verwendete. Angesichts der beteiligten Parameter hätte die Indexsuche eine Suche nach zig Millionen Datensätzen für die Ausgabe erforderlich gemacht.

Ich habe die beiden Prozeduren aus dem Cache gelöscht und den .NET-Client das SP erneut mit denselben Parametern ausführen lassen (die einen großen Datumsbereich für einen Kunden mit vielen Aktivitäten enthielten) SP wurde sofort zurückgegeben. Der zwischengespeicherte Plan verwendete denselben Index-Scan, der zuvor im ARITHABORT ON-Plan enthalten war - diesmal war der Plan jedoch für ARITHABORT OFF. Wir haben SP mit denselben Parametern in SSMS und sofort wieder Ergebnisse. Jetzt haben wir gesehen, dass ein zweiter Plan für ARITHABORT ON mit dem Index-Scan zwischengespeichert wurde.

Wir haben dann den Cache geleert, das SP in SSMS mit einem engen Datumsbereich) ausgeführt und ein sofortiges Ergebnis erhalten. Wir haben festgestellt, dass der resultierende zwischengespeicherte Plan eine Indexsuche hatte, da dieselbe Ausgabe zuvor verarbeitet wurde mit einem Scan (der auch im ursprünglichen Plan mit ARITHABORT OFF eine Suche war). Wieder von SSMS aus führten wir den SP aus, diesmal mit demselben großen Datumsbereich, und sahen dieselbe schreckliche Leistung, die wir in der ursprünglichen .NET-Anfrage hatten .

Kurz gesagt, die Ungleichheit hatte nichts mit dem tatsächlichen Wert von ARITHABORT zu tun - mit dem Ein- oder Ausschalten konnten wir von beiden Clients 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 selbst einen negativen Einfluss auf die Abfrageoptimierung haben kann, bestätigen unsere Tests, dass Martin korrekt ist - die Ursache war Parameter-Sniffing und das Ergebnis Plan ist nicht für alle Parameterbereiche optimal.

13
mdoyle

Hatte gerade dieses Problem. Wie hier gesagt, ist die Hauptursache mehrere Abfragepläne, 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).

1
Alan D. Nelson

Dies erinnert mich an genau das Problem, das ich in den Tagen von SQL Server 2008 hatte. In unserem Fall haben wir plötzlich festgestellt, 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 ARITHABORT im Schritt des Jobs 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 geöffnet, und anfangs können sie es auch nicht herausfinden. Das Ticket wurde an ein sehr hochrangiges PFE-Team weitergeleitet, und zwei Support-PFEs haben versucht, dieses Problem herauszufinden.

Der letzte Grund ist, dass die Benutzeranmeldeinformationen (um den Jobschritt auszuführen) nicht auf die Statistiken der zugrunde liegenden Tabellen (auf der Seite des Verbindungsservers) zugreifen können und daher der Ausführungsplan nicht optimiert ist.

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

Berechtigungen für SQL Server und SQL-Datenbank

Um das Statistikobjekt anzeigen zu können, muss der Benutzer die Tabelle besitzen oder Mitglied der festen Serverrolle sysadmin, der festen Datenbankrolle db_owner oder der festen Datenbankrolle db_ddladmin sein.

SQL Server 2012 SP1 ändert die Berechtigungsbeschränkungen und ermöglicht Benutzern mit SELECT-Berechtigung, diesen Befehl zu verwenden. Beachten Sie, dass die folgenden Anforderungen vorhanden sind, damit SELECT-Berechtigungen ausreichen, um den Befehl auszuführen:

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

(enter image description here

Hoffe, diese Erfahrung kann der Community irgendwie helfen.

1
jyao