it-swarm.com.de

Abfragezeitüberschreitung bei Ausführung aus dem Web, aber superschnell bei Ausführung über SSMS

Ich versuche, die Quelle eines SQL-Timeouts in einer von mir gewarteten Webanwendung zu debuggen. Ich habe den Quellcode des C # -Codes hinter sich, also weiß ich genau, welcher Code läuft. Ich habe die Anwendung bis zur Zeile debuggt, die den SQL-Code ausführt, der das Zeitlimit überschreitet, und ich beobachte die Abfrage, die in SQL Profiler ausgeführt wird. 

Wenn diese Abfrage aus dem Web ausgeführt wird, tritt nach 30 Sekunden eine Zeitüberschreitung auf. Wenn ich jedoch die Abfrage genau wie im Profiler ausschneide und in SSMS stecke und ausführen, wird sie fast sofort wieder angezeigt. Ich habe das Problem darauf zurückgeführt, dass ARITHABORT in der Verbindung, die das Web verwendet, auf OFF gesetzt ist (wenn ich also ARITHABORT in der SSMS-Sitzung auf OFF schalte, läuft es lange, und wenn ich es wieder einschalte, wird es ausgeführt sehr schnell). Die Beschreibung von ARITHABORT zu lesen scheint jedoch nicht zutreffend zu sein. Ich mache nur eine einfache SELECT-Anweisung und es wird überhaupt keine Arithmetik ausgeführt. Nur ein einziger INNER JOIN mit einer WHERE-Bedingung:

Warum verursacht ARITHABORT OFF dieses Verhalten in diesem Zusammenhang? Gibt es eine Möglichkeit, die ARITHABORT-Einstellung für diese Verbindung von SSMS aus zu ändern? Ich verwende SQL Server 2008.

39
Michael Bray

Ihr C # -Code sendet also eine Ad-hoc-SQL-Abfrage mit welcher Methode an SQL Server? Haben Sie überlegt, eine gespeicherte Prozedur zu verwenden? Das würde wahrscheinlich die gleiche Leistung (zumindest im Motor) gewährleisten, unabhängig davon, wer es genannt hat. 

Warum? Die Einstellung ARITHABORT ist eine der Faktoren, die das Optimierungsprogramm untersucht, wenn es bestimmt, wie die Abfrage ausgeführt werden soll (insbesondere für den Planabgleich). Es ist möglich, dass der Plan im Cache die gleiche Einstellung wie SSMS hat, also den zwischengespeicherten Plan verwendet. Mit der entgegengesetzten Einstellung erzwingt Ihr C # -Code jedoch eine Neukompilierung (oder Sie treffen tatsächlich einen wirklich BAD - Plan im Cache), was in vielen Fällen die Leistung beeinträchtigen kann. 

Wenn Sie bereits eine gespeicherte Prozedur aufrufen (Sie haben Ihre Abfrage nicht gepostet, obwohl ich meine, dass Sie dies beabsichtigt haben), können Sie versuchen, OPTION (RECOMPILE) zur anstößigen Abfrage (oder Abfragen) in der gespeicherten Prozedur hinzuzufügen. Dies bedeutet, dass diese Anweisungen immer neu kompiliert werden, dies kann jedoch die Verwendung des falschen Plans verhindern, den Sie zu treffen scheinen. Eine weitere Option besteht darin, sicherzustellen, dass der Batch beim Kompilieren der gespeicherten Prozedur mit SET ARITHABORT ON ausgeführt wird.

Schließlich scheinen Sie zu fragen, wie Sie die Einstellung ARITHABORT in SSMS ändern können. Ich denke, Sie wollten fragen, wie Sie die Einstellung ARITHABORT in Ihrem Code erzwingen können. Wenn Sie sich dazu entschließen, weiterhin Ad-hoc-SQL von Ihrer C # -Anwendung aus zu senden, können Sie einen Befehl natürlich als Text senden, der mehrere durch Semikolons getrennte Anweisungen enthält, z. B .:

SET ARITHABORT ON; SELECT ...

Weitere Informationen dazu, warum dieses Problem auftritt, finden Sie in Erland Sommarskogs großartigem Artikel:

38
Aaron Bertrand

Diese Antwort enthält eine Möglichkeit, dieses Problem zu beheben:

Durch Ausführen der folgenden Befehle als Administrator für die Datenbank werden alle Abfragen unabhängig von der Einstellung für ARITHABORT wie erwartet ausgeführt.

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

Aktualisieren

Es scheint, dass die meisten Menschen dieses Problem sehr selten haben, und die obige Technik ist eine anständige einmalige Lösung. Wenn jedoch bei einer bestimmten Abfrage dieses Problem mehr als einmal auftritt, besteht eine längerfristige Lösung darin, Abfragehinweise wie OPTIMIZE FOR und OPTION(Recompile) zu verwenden, wie in diesem Artikel beschrieben.

12

Ich hatte dieses Problem schon oft, aber wenn Sie eine gespeicherte Prozedur haben, bei der das gleiche Problem gelöscht und die gespeicherte Prozedur neu erstellt wird, wird das Problem behoben.

Es wird als Parameter-Sniffing bezeichnet. Sie müssen die Parameter immer in der gespeicherten Prozedur lokalisieren, um dieses Problem in Zukunft zu vermeiden.

Ich verstehe, dass dies möglicherweise nicht das ist, was das ursprüngliche Poster will, aber es kann jemandem mit dem gleichen Problem helfen.

3
Novice in.NET

Wenn Sie Entity Framework verwenden, müssen Sie wissen, dass die Abfrageparameter für Zeichenfolgenwerte als nvarchar an die Datenbank gesendet werden. Wenn die zu vergleichende Datenbankspalte eine varchar ist, kann es je nach Sortierung eine "IMPLICIT CONVERSION" erfordern, die Indizes vermeidet. 

Schließlich fand ich es dank dieses Artikels heraus: https://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-cause-index-scans/

1
edumen

Ich hatte das gleiche Problem und es wurde durch Ausführen der Prozedur "WITH RECOMPILE" behoben. Sie können auch versuchen, das Parameter-Sniffing zu verwenden. Mein Problem hatte mit dem SQL-Cache zu tun. 

0
Manmeet

Wenn Sie Ihren Code ändern können, um das Parameter-Sniffing für unbekannten Hinweis zu optimieren, ist dies die beste Option. Wenn Sie Ihren Code nicht ändern können, ist exec sp_recompile 'Name der Prozedur' die beste Option, die nur die gespeicherte Prozedur zwingt, einen neuen Ausführungsplan abzurufen. Das Löschen und Wiederherstellen einer Prozedur hätte einen ähnlichen Effekt, könnte jedoch zu Fehlern führen, wenn jemand versucht, die Prozedur auszuführen, während Sie sie gelöscht haben. DBCC FREEPROCCACHE verwirft alle Ihre zwischengespeicherten Pläne, die Ihr System zerstören können, einschließlich einer Vielzahl von Timeouts in einer Produktionsumgebung mit umfangreichen Transaktionen. Das Setzen von Arithabort ist keine Lösung für das Problem, aber es ist ein nützliches Werkzeug, um herauszufinden, ob das Parameter-Sniffing das Problem ist.

0
N. Rhoades

Ich habe das gleiche Problem, als ich versuchte, SP von SMSS aufzurufen, es dauerte 2 Sekunden, während von der Webanwendung (ASP.NET) etwa 3 Minuten dauerten.

Ich habe alle Lösungsvorschläge sp_recompile, DBCC FREEPROCCACHE und DBCC DROPCLEANBUFFERS ausprobiert, aber nichts wurde mein Problem behoben, aber wenn versucht wurde, das Parameter-Sniffing auszuführen, hat es den Trick gelöst und es hat gut funktioniert. 

0
Karim Tawfik