it-swarm.com.de

Wo finde ich die Ursache des Problems, wenn eine zuvor schnelle SQL-Abfrage langsam ausgeführt wird?

Hintergrund

Ich habe eine Abfrage, die für SQL Server 2008 R2 ausgeführt wird und ungefähr 12 verschiedene "Tabellen" verknüpft und/oder links verknüpft. Die Datenbank ist ziemlich groß mit vielen Tabellen über 50 Millionen Zeilen und etwa 300 verschiedenen Tabellen. Es ist für ein großes Unternehmen mit 10 Lagern im ganzen Land. Alle Lager lesen und schreiben in die Datenbank. Es ist also ziemlich groß und ziemlich beschäftigt.

Die Abfrage, mit der ich Probleme habe, sieht ungefähr so ​​aus:

select t1.something, t2.something, etc.
from Table1 t1
    inner join Table2 t2 on t1.id = t2.t1id
    left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
    [etc]...
where t1.something = 123

Beachten Sie, dass sich einer der Joins in einer nicht korrelierten Unterabfrage befindet.

Das Problem ist, dass ab heute Morgen ohne Änderungen (die ich oder jemand in meinem Team kennt) am System die Abfrage, deren Ausführung normalerweise etwa 2 Minuten dauert, anderthalb Stunden dauerte - wenn sie ausgeführt wurde lief überhaupt. Der Rest der Datenbank summt ganz gut mit. Ich habe diese Abfrage aus dem Sproc herausgenommen, in dem sie normalerweise ausgeführt wird, und ich habe sie in SSMS mit fest codierten Parametervariablen mit derselben Langsamkeit ausgeführt.

Die Seltsamkeit ist, dass die Abfrage einwandfrei ausgeführt wird, wenn ich die nicht korrelierte Unterabfrage in eine temporäre Tabelle wirf und sie dann anstelle der Unterabfrage verwende. Auch (und das ist das seltsamste für mich), wenn ich diesen Code am Ende der Abfrage hinzufüge, läuft die Abfrage großartig:

and t.name like '%'

Ich bin aus diesen kleinen Experimenten (möglicherweise falsch) zu dem Schluss gekommen, dass der Grund für die Verlangsamung in der Einrichtung des zwischengespeicherten Ausführungsplans von SQL liegt. Wenn die Abfrage etwas anders ist, muss ein neuer Ausführungsplan erstellt werden.

Meine Frage lautet : Wenn eine Abfrage, die früher schnell ausgeführt wurde, plötzlich mitten in der Nacht langsam ausgeführt wird und außer dieser einen Abfrage nichts anderes betroffen ist, wie kann ich sie beheben und wie kann ich sie beheben? verhindern, dass es in Zukunft passiert? Woher weiß ich, was SQL intern tut, um es so langsam zu machen (wenn die fehlerhafte Abfrage ausgeführt wird, könnte ich den Ausführungsplan abrufen, aber er wird nicht ausgeführt - möglicherweise würde mir der erwartete Ausführungsplan etwas geben?)? Wenn dieses Problem mit dem Ausführungsplan zusammenhängt, wie kann ich SQL davon abhalten, wirklich beschissene Ausführungspläne für eine gute Idee zu halten?

Dies ist auch kein Problem beim Parameter-Sniffing. Ich habe das schon einmal gesehen, und das ist es nicht, denn selbst wenn ich die Variablen in SSMS hart codiere, bekomme ich immer noch eine langsame Leistung.

39
Trevor

Wenn eine Abfrage, die früher schnell ausgeführt wurde, mitten in der Nacht plötzlich langsam ausgeführt wird und außer dieser einen Abfrage nichts anderes betroffen ist, wie kann ich sie beheben?

Sie können zunächst überprüfen, ob sich der Ausführungsplan noch im Cache befindet. Überprüfen Sie sys.dm_exec_query_stats , sys.dm_exec_procedure_stats und sys.dm_exec_cached_plans . Wenn der Plan für fehlerhafte Ausführung immer noch zwischengespeichert ist, können Sie ihn analysieren und die Ausführungsstatistiken überprüfen. Die Ausführungsstatistiken enthalten Informationen wie logische Lesevorgänge, CPU-Zeit und Ausführungszeit. Diese können starke Hinweise auf das Problem geben (z. B. großer Scan vs. Blockieren). Unter Identifizieren von Problemabfragen finden Sie eine Erklärung zur Interpretation der Daten.

Dies ist auch kein Problem beim Parameter-Sniffing. Ich habe das schon einmal gesehen, und das ist es nicht, denn selbst wenn ich die Variablen in SSMS hart codiere, bekomme ich immer noch eine langsame Leistung.

Ich bin nicht überzeugt. Hartcodierte Variablen in SSMS beweisen nicht, dass der frühere schlechte Ausführungsplan nicht gegen eine verzerrte Eingabe kompiliert wurde. Bitte lesen Sie Parameter Sniffing, Embedding und die RECOMPILE-Optionen , um einen sehr guten Artikel zu diesem Thema zu erhalten. Langsam in der Anwendung, schnell in SSMS? Das Verständnis von Performance Mysteries ist eine weitere hervorragende Referenz.

Ich bin aus diesen kleinen Experimenten (möglicherweise falsch) zu dem Schluss gekommen, dass der Grund für die Verlangsamung in der Einrichtung des zwischengespeicherten Ausführungsplans von SQL liegt. Wenn die Abfrage etwas anders ist, muss ein neuer Ausführungsplan erstellt werden.

Dies kann leicht getestet werden. SET STATISTICS TIME ON zeigt Ihnen die Kompilierungs- und Ausführungszeit. SQL Server: Statistik-Leistungsindikatoren zeigen auch an, ob die Kompilierung ein Problem darstellt (ehrlich gesagt halte ich es für unwahrscheinlich).

Es gibt jedoch etwas Ähnliches, das Sie möglicherweise treffen: das Abfrage-Grant-Gate. Weitere Informationen finden Sie unter Grundlegendes zur Speichergewährung von SQL Server . Wenn Ihre Abfrage zu einem Zeitpunkt einen großen Zuschuss anfordert, für den kein Speicher verfügbar ist, muss sie warten, und für die Anwendung wird alles als "langsame Ausführung" angezeigt. Wenn Sie Wartestatistiken analysieren, wird angezeigt, ob dies der Fall ist.

Eine allgemeinere Diskussion darüber, was gemessen und wonach gesucht werden muss, finden Sie unter Analysieren der SQL Server-Leistung

33
Remus Rusanu

Dies ist ein Fluch beim Ausführen komplexer Abfragen in SQL Server. Zum Glück kommt es nicht so oft vor.

Sehen Sie sich den Abfrageplan für die Abfrage an (wenn sie langsam ausgeführt wird). Ich vermute, Sie werden einen verschachtelten Loop-Join finden, der ein- oder mehrmals in Tabellen ohne Indizes für den Join auftritt. Das verlangsamt die Dinge wirklich. Um dies schnell vorzuspulen, können Sie dies mit einem Hinweis beheben. Fügen Sie am Ende der Abfrage Folgendes hinzu:

OPTION (MERGE JOIN, HASH JOIN)

Dies hat dieses Problem in der Vergangenheit allgemein für mich behoben.

Was möglicherweise passiert, ist, dass geringfügige Änderungen an der Tabelle (oder an der Verfügbarkeit von temporärem Speicherplatz) dazu führen, dass die SQL-Optimierung einen langsameren Verknüpfungsalgorithmus bevorzugt. Dies kann sehr subtil und sehr plötzlich sein. Wenn Sie eine temporäre Tabelle erstellen, verfügt das Optimierungsprogramm über weitere Informationen zur Tabelle (z. B. deren Größe), sodass ein besserer Plan erstellt werden kann.

7
Gordon Linoff

Ich habe kürzlich dasselbe Problem festgestellt, das mich auf diese Seite gebracht hat.

@MartinSmith war auf etwas, als er empfahl, Ihre Statistiken zu aktualisieren und den Plan zu erklären. Ich möchte hinzufügen, dass Sie auch versuchen sollten, sicherzustellen, dass Sie sich mit laufenden Jobs/Abfragen befassen, die zu Sperren führen und dadurch die Reaktionszeit verlangsamen können.

In meinem Fall war der Schuldige das Sammeln von Tabellenstatistiken. Aus irgendeinem Grund wurde es in dem Fenster, das es haben sollte, nicht abgeschlossen und lief weiter, wenn die Benutzer wieder aufgenommen wurden. Ich fand den Prozess, beendete ihn und die Anfragen antworteten erneut.

Ich hoffe das hilft jemand anderem

3
daffyjeje

Normalerweise ist es ein fehlender Index, der diese Art von Problem verursacht.

Normalerweise führe ich die Abfrage mit SQL Management Studio aus und aktiviere "Aktuellen Ausführungsplan einschließen (STRG + M)", um herauszufinden, welcher Join den größten Prozentsatz aufweist.

Die Anwendung konzentriert sich nicht auf den Engpass, aber Sie können ihn "schnell" finden, wenn Sie nur das Ergebnis betrachten.

beispiel hier: 48PercentForTop

3
Xavier

Sie müssen auch überprüfen, ob eine Serversicherung oder Archivierungs-/Indizierungsjobs ausgeführt werden, wenn in T-SQL\Procedure Leistungsprobleme auftreten.

0
Amol Nimbalkar