Warum ist meine Abfrage plötzlich langsamer als gestern?

76

[Anreden]

(ankreuzen)

[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,

Ich habe ein (Zutreffendes ankreuzen)

[ ] query [ ] stored procedure [ ] database thing maybe  

das lief gut (falls zutreffend)

[ ] yesterday [ ] in recent memory [ ] at some point 

aber ist jetzt plötzlich langsamer.

Ich habe bereits überprüft, ob es nicht blockiert wird und ob es nicht Opfer einer lang andauernden Wartungsaufgabe, eines Berichts oder eines anderen Out-of-Band-Prozesses ist.

Was ist das Problem, was soll ich tun und welche Informationen kann ich bereitstellen, um Hilfe zu erhalten?

[*Insert appropriate closing remarks*]
Erik Darling
quelle

Antworten:

88

Lieber [dein Name hier]!

Oh nein, das tut mir leid! Beginnen wir mit einigen Grundlagen, um Sie im Handumdrehen zu reparieren.

Das, worauf Sie stoßen, heißt Parameter Sniffing

Es ist ein Ausweg wiggy seltsames Problem. Der Name rollt direkt von der Zunge. Wie das deutsche Wort für Eichhörnchen.

Und normalerweise ist es dein Freund.

Wenn eine Abfrage Ihren Server erreicht, muss ein Plan erstellt werden. Um später Zeit und Ressourcen zu sparen, wird ein Ausführungsplan zwischengespeichert, der auf den geschätzten Zeilen basiert, die der Parameter zur Verarbeitung und Rückgabe Ihres Codes veranlasst.

Der einfachste Weg, um sich vorzustellen, wie es schlecht läuft, besteht darin, sich eine gespeicherte Prozedur vorzustellen, die Dinge aus zwei schiefen Populationen zählen muss.

Zum Beispiel:

  • Leute mit CrossFit-Shirts, die nicht verletzt sind: Zero

  • Menschen, die CrossFit-Shirts tragen und zusammenzucken, wenn sie zusammenzucken: Alle

Offensichtlich müsste eine Ausführung dieses Codes viel mehr Arbeit als eine andere leisten, und die Abfragepläne, die Sie für ganz andere Aufgaben benötigen, würden ganz anders aussehen.

Womit habe ich zu kämpfen?

Es ist wirklich schwierig, dieses Problem zu finden, zu testen und zu beheben.

  • Es ist schwer zu finden, weil es nicht konsequent passiert
  • Es ist schwer zu testen, da Sie wissen müssen, welche Parameter unterschiedliche Pläne verursachen
  • Es ist schwer zu beheben, da manchmal eine Abfrage- und Indexoptimierung erforderlich ist
  • Es ist schwer zu beheben, da Sie möglicherweise keine Abfragen oder Indizes ändern können
  • Es ist schwer zu beheben, da es auch bei Änderungen an Abfragen oder Indizes vorkommen kann, dass sie zurückkehren

Schnellkorrekturen

Manchmal brauchen Sie nur ein wenig Klarheit. Oder besser gesagt, Ihr Plan-Cache funktioniert.

Wenn es sich um eine gespeicherte Prozedur handelt

Versuche zu rennen EXEC sys.sp_recompile @objname = N'schema.procname'. Dadurch wird die Prozedur veranlasst, beim nächsten Ausführen einen neuen Plan neu zu kompilieren.

Was das nicht behebt:

  • Prozesse, die gerade ausgeführt werden.

Was dies nicht garantiert:

  • Der nächste Prozess, der nach dem erneuten Kompilieren ausgeführt wird, verwendet einen Parameter, der Ihnen einen guten Plan liefert.

Sie können auch sp_recompileauf eine Tabelle oder Ansicht zeigen, aber seien Sie gewarnt, dass der gesamte Code, der diese Tabelle oder Ansicht berührt, neu kompiliert wird. Dies könnte das Problem erheblich erschweren.

Wenn es eine parametrisierte Abfrage ist

Ihre Arbeit ist etwas schwieriger. Sie müssen das SQL-Handle aufspüren. Sie möchten nicht den gesamten Plan-Cache freigeben - genau wie bei der Verwendung sp_recompilefür eine Tabelle oder eine Ansicht können Sie eine ganze Reihe unbeabsichtigter Konsequenzen auslösen (ha ha ha).

Der einfachste Weg, dieses Kommando herauszufinden, ist sp_BlitzWho *! Es gibt eine Spalte mit dem Namen "Fix Parameter Sniffing", die einen Befehl zum Entfernen eines einzelnen Plans aus dem Cache enthält. Dies hat jedoch die gleichen Nachteile wie das Neukompilieren.

Was das nicht behebt:

  • Prozesse, die gerade ausgeführt werden.

Was dies nicht garantiert:

  • Der nächste Prozess, der nach dem erneuten Kompilieren ausgeführt wird, verwendet einen Parameter, der Ihnen einen guten Plan liefert.

Ich brauche immer noch Hilfe!

Wir werden die folgenden Dinge brauchen:

  • Der gute Abfrageplan, wenn möglich
  • Der schlechte Abfrageplan
  • Die verwendeten Parameter
  • Die fragliche Abfrage
  • Tabellen- und Indexdefinitionen

Abfragepläne und Abfrage abrufen

Wenn die Abfrage ausgeführt wird, können Sie sp_BlitzWho * oder sp_WhoIsActive verwenden , um aktuell ausgeführte Abfragen zu erfassen.

EXEC sp_BlitzWho;

EXEC sp_WhoIsActive @get_plans = 1;

NÜSSE

Wenn die Abfrage derzeit nicht ausgeführt wird, können Sie sie mit sp_BlitzCache * im Plan-Cache überprüfen .

Wenn Sie mit SQL Server 2016+ arbeiten und den Abfragespeicher aktiviert haben, können Sie sp_BlitzQueryStore * verwenden.

EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';

EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';

Auf diese Weise können Sie zwischengespeicherte Versionen Ihrer gespeicherten Prozedur ermitteln. Wenn es sich nur um parametrisierten Code handelt, ist Ihre Suche etwas schwieriger. Dies kann jedoch helfen:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

Sie sollten eine ziemlich ähnliche Ausgabe von diesen sehen. Auch hier ist der Abfrageplan, der zu einer coolen blau-klickenden Spalte einlädt, Ihr Freund.

NÜSSE

Die einfachste Möglichkeit, Pläne freizugeben, besteht darin, den Plan * einzufügen oder die XML-Datei in den Pastebin zu kopieren. Klicken Sie dazu auf eine der einladenden blauen Klickspalten. Ihr Abfrageplan sollte auf einer neuen Registerkarte von SSMS angezeigt werden.

NÜSSE

Wenn Sie den Code und die Abfrage Ihres Unternehmens nicht genau kennen, können Sie Ihren Plan mit dem kostenlosen Plan Explorer-Tool von Sentry One anonymisieren. Denken Sie daran, dies erschwert die Hilfe - anonymisierter Code ist viel schwieriger zu lesen und herauszufinden.

Alle diese Tools, über die wir gesprochen haben, sollten den Abfragetext zurückgeben. Sie müssen hier nichts weiter tun.

Das Erhalten der Parameter ist etwas schwieriger. Wenn Sie den Plan-Explorer verwenden , finden Sie unten eine Registerkarte, auf der alle für Sie aufgelistet sind.

NÜSSE

Wenn Sie sp_BlitzCache * verwenden, gibt es eine anklickbare Spalte, in der Sie die Ausführungsanweisung für gespeicherte Prozeduren finden.

NÜSSE

Abrufen der Tabellen- und Indexdefinitionen

Sie können ganz einfach mit der rechten Maustaste in SSMS klicken, um das Skript auszuführen.

NÜSSE

Wenn Sie alles auf einmal sehen möchten, hilft Ihnen sp_BlitzIndex *, wenn Sie es direkt auf einen Tisch richten .

EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
                       @SchemaName = 'dbo',
                       @TableName = 'Users';

Dadurch erhalten Sie die Tabellendefinition (jedoch nicht als create-Anweisung) und erstellen Anweisungen für alle Ihre Indizes.

Durch das Sammeln und Hinzufügen dieser Informationen zu Ihrer Frage sollten die Leute genügend Informationen erhalten, um Ihnen zu helfen, oder Sie in die richtige Richtung weisen.

Ich will es selbst machen!

Na ja, cool. Ich freue mich für dich. Du verrückter Mensch.

Es gibt viele Möglichkeiten, wie die Leute glauben, dass sie das Parameter-Sniffing "reparieren":

Aber diese deaktivieren das Parameter-Sniffing auf verschiedene Arten. Das heißt nicht, dass sie das Problem nicht lösen können, sondern nur nicht wirklich zur eigentlichen Ursache gelangen.

Das liegt daran, dass es normalerweise schwierig ist, zur eigentlichen Ursache zu gelangen. Sie müssen nach diesen lästigen "Planqualitätsproblemen" suchen.

Beginnen Sie mit den schnellen und langsamen Plänen und suchen Sie nach Unterschieden wie:

  • Verwendete Indizes
  • Bestellung beitreten
  • Seriell vs Parallel

Suchen Sie auch nach verschiedenen Operatoren, die Ihren Code für das Parameter-Sniffing empfindlich machen:

  • Lookups
  • Sortiert
  • Join-Typ
  • Speicherzuweisungen (und damit verbundene Verschüttungen)
  • Spulen

Lassen Sie sich nicht zu sehr auf Suchanfragen, Indexfragmentierungen oder die Kultgegenstände der Fracht ein.

Normalerweise gibt es ein ziemlich einfaches Indizierungsproblem. Manchmal muss der Code ein wenig umgeschrieben werden.

Wenn Sie mehr über Parameter-Sniffing erfahren möchten:

Wenn Sie dies lesen und der Meinung sind, dass ich einen Link oder ein hilfreiches Tool verpasst habe, hinterlassen Sie einen Kommentar. Ich werde mein Bestes tun, um dies auf dem neuesten Stand zu halten.


Erik Darling
quelle
28

Das Parameter-Sniffing ist nicht die einzige mögliche Ursache für die unterschiedliche Leistung einer Abfrage. Jeder der folgenden häufigen Gründe kann dieselben Symptome zeigen:

  1. Die Datenverteilung / das Datenvolumen wurde geändert und der Entscheidungspunkt eines Optimierungssuchbaums überschritten
  2. Indizes / Dateien wurden fragmentiert
  3. Statistiken wurden aktualisiert / hinzugefügt / gelöscht oder sind aufgrund von Datenänderungen veraltet und irreführend geworden
  4. Windows-Speicherauslastung geändert
  5. Transaktionsprotokolle sind voll und werden nicht abgeschnitten, was zu einer wiederholten physischen Dateierweiterung führt
  6. Schema geändert - Index / indizierte Ansicht / Spalte / Einschränkung hinzugefügt, geändert oder gelöscht, Datentyp geändert usw.
  7. Trace Flag Einstellungen geändert
  8. Windows Update wurde angewendet
  9. Datenbank- oder Servereinstellung geändert
  10. Server-CU-Ebene geändert
  11. Sitzungseinstellungen der Clientanwendung geändert

Die Punkte 6 - 11 in dieser Liste können nur ausgeführt werden, wenn explizite Maßnahmen ergriffen wurden. Ich vermute, Sie wollten diese ausschließen, aber derjenige, der die Herausforderung erlebt, ist sich oft nicht bewusst, dass jemand anders Änderungen vorgenommen hat, und das ist eine Überprüfung wert, bevor Sie sich auf den Weg machen, um die Cache-Einträge des Plans zu löschen.

SQLRaptor
quelle
1
Danke für die Bearbeitung Paul. @sp_BlitzErik - Es war nicht meine Absicht, zu bestimmten Themen Ratschläge zu erteilen, nur um das Bewusstsein dafür zu schärfen, dass sie existieren, und es könnte sich lohnen, sie zu prüfen. Dies soll in keiner Weise Ihren großartigen Beitrag schmälern. Sie haben sich professionell und mit guter Laune eingehend mit Parameter-Sniffing befasst. Ich habe es genossen, es zu lesen. Ich möchte nur sicherstellen, dass jemand, der diesen Beitrag besucht, nach dem eingängigen Titel auf die alternativen möglichen Ursachen aufmerksam gemacht wird. Meiner Meinung nach ist Ihr Beitrag wertvoller, aber wenn Sie trotzdem möchten, dass ich ihn lösche, lassen Sie es mich wissen.
SQLRaptor
Nein überhaupt nicht. Ich würde niemals jemanden bitten, eine Antwort zu löschen, die nicht falsch oder schädlich ist. Ich denke immer noch, dass Sie einige Details hinzufügen könnten, aber das liegt letztendlich an Ihnen.
Erik Darling
10

Um die vorhandenen Antworten zu ergänzen, falls sie nicht geholfen haben, wenn sich Ihre Fragen am nächsten Tag "plötzlich" anders verhalten, überprüfen Sie Folgendes:

  • Hat sich das Schema für die verwendeten Tabellen seit dem letzten Mal geändert? Bei SSMS können Sie im Objekt-Explorer mit der rechten Maustaste auf den Server klicken und wählen Reports → Standard Reports → Schema Changes History.
  • Hat sich die Anzahl der Gegenstände dramatisch erhöht? Möglicherweise ist Ihre Abfrage viel langsamer, wenn die verwendeten Tabellen viele Daten enthalten.
  • Nutzt jemand anderes die Datenbank gleichzeitig mit Ihnen? Wählen Sie vielleicht Zeitfenster, in denen Sie sich nicht gegenseitig in die Arbeit einmischen.
  • Wie sehen die Systemstatistiken aus? Möglicherweise ist der Server heiß und drosselt die CPU, oder auf den Festplatten ist nicht genügend Speicherplatz vorhanden oder es wird kein Speicherplatz mehr ausgetauscht. Möglicherweise liegt ein anderes Hardwareproblem wie ein Feuer oder eine Flut im Serverraum vor.
user1306322
quelle
7

Eine andere Möglichkeit besteht darin, dass Ihr Infrastructure Team Tools wie vMotion auf VMware verwendet und die VM, die Ihre SQL-Instanz unterstützt, nahtlos von Host zu Host verschoben wird, ohne dass der DBA davon Kenntnis hat.

Dies ist ein echtes Problem, wenn Ihre Infrastruktur ausgelagert ist ... Ich habe einen echten Albtraum damit.

Schritt für Schritt
quelle