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_recompile
auf 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_recompile
fü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;
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.
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.
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.
Wenn Sie sp_BlitzCache * verwenden, gibt es eine anklickbare Spalte, in der Sie die Ausführungsanweisung für gespeicherte Prozeduren finden.
Abrufen der Tabellen- und Indexdefinitionen
Sie können ganz einfach mit der rechten Maustaste in SSMS klicken, um das Skript auszuführen.
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.