Ich habe eine Löschanweisung, die einen schlechten Plan verwendet, wenn sie in einer gespeicherten Prozedur ausgeführt wird, aber einen viel besseren Plan wählt, wenn sie ad-hoc ausgeführt wird.
Ich habe alle Indizes für die von der Abfrage verwendeten Tabellen neu erstellt und alle Caches gelöscht. Der Optimierer wählt immer noch den falschen Plan für die gespeicherte Prozedur.
Ich möchte wissen, warum das Optimierungsprogramm für die gespeicherte Prozedur einen anderen Ausführungsplan verwendet als für Ad-hoc-SQL.
UPDATE: Ich denke, es müssen doch die Parameter gewesen sein. Wenn ich den Ad-hoc-Code mit der fest codierten Variablen ausgeführt habe, kann ich den "schlechten" Plan mit dem richtigen Wert erhalten (es ist ein Datum, Werte, die ein Jahr alt sind scheinen den "guten" Plan zu generieren). Nun zum Versuch, den "guten" Plan mithilfe eines Abfragehinweises auf den Prozess zu erzwingen.
LÖSUNG: Am Ende habe ich den gewünschten Plan mit dem Hinweis OPTIMIEREN FÜR UNBEKANNT erhalten.
quelle
WHERE
Klausel?Antworten:
Übliche Verdächtige:
Punkt 1: Der Optimierer kann den besten Plan für die Konstanten auswählen.
Ändern Sie die Konstanten = ändern Sie den Plan. Ein parametrisierter Plen ist resuierbar
Punkt 2 führt implizite Konvertierungen ein, da der Datentyp Vorrang hat,
z. B. die varchar-Spalte im Vergleich zum Parameter nvarchar
Punkt 3: Verwenden Sie die Parametermaskierung oder OPTIMIEREN SIE FÜR UNBEKANNT.
Bearbeiten: Zum Testen: Speichern Sie den gespeicherten Prozess, führen Sie sp_updatestats aus und führen Sie ihn erneut aus. Dadurch werden zwischengespeicherte Pläne ungültig, was besser ist als das Löschen des Plan-Cache
Bearbeiten: nach dem Kommentar von jcolebrand
Sie können das Schnüffeln auf verschiedene Arten deaktivieren. Die wichtigsten 3 sind
Parametermaskierung:
Die Maskierung und der OPTIMIZE-Hinweis haben den gleichen Effekt (möglicherweise aus verschiedenen Gründen). Das heißt, der Optimierer muss Statistiken verwenden und die Datenverteilung ( Hinweis: wird noch von Mark Storey-Smith getestet )
die Parameter nach ihren eigenen Vorzügen bewerten ., anstatt was sie zuletzt angerufen hatten. Der Optimierer kann neu kompilieren oder nicht. SQL Server 2005 fügte eine Neukompilierung auf Anweisungsebene hinzu, sodass weniger Auswirkungen auftratenIch bin mir nicht sicher, warum ein Plan mit "beschnüffelten" Parametern im Vergleich zu maskierten / "unbekannten" Parametern "klebrig" ist.
Ich habe seit SQL Server 2000 die Parametermaskierung für alle außer dem einfachsten Code verwendet. Ich habe festgestellt, dass dies bei komplexerem Code wahrscheinlich vorkommt. Und bei meinem alten Job habe ich einige Berichtsprozesse, dass ich die Standardeinstellungen der Planparameter ändern könnte. Ich denke, der "Frachtkult" -Ansatz war einfacher als ein Support-Anruf.
Edit 2, 12. Oktober 2011, nach einigem Chat
Die Parametermaskierung und OPTIMIZE FOR UNKNOWN haben, soweit ich das beurteilen kann, den gleichen Effekt.
Der Hinweis ist sauberer als die Maskierung, wurde jedoch mit SQL Server 2008 hinzugefügt.
Das Parameter-Sniffing erfolgt zur Kompilierungszeit.
WITH RECOMPILE generiert bei jeder Ausführung einen neuen Plan. Dies bedeutet, dass eine schlechte Auswahl der Standardeinstellungen den Plan beeinflusst. Bei meinem letzten Job konnte ich dies leicht mit einem Berichtscode demonstrieren: Durch Ändern der Parameterstandards wurde der Plan unabhängig von den angegebenen Parametern geändert.
Dieser MS Connect-Artikel ist interessant: Suboptimale Indexverwendung innerhalb der gespeicherten Prozedur (in einer der folgenden SO-Antworten erwähnt)
Offene Fragen
Gilt das Schnüffeln immer noch mit WITH RECOMPILE? Das heißt, wenn der Optimierer weiß, dass er den Plan verwerfen muss, zielt er auf eine Wiederverwendung ab?
Warum sind schnüffelnde Pläne "klebrig"?
Links von SO:
/programming//q/272726/27535
Remus Rusanu (MS SQL Team) und ich hatten hier auf SO einen Bunfight
quelle
OPTION (RECOMPILE)
oder mit dem gesamten Prozess ausführenWITH RECOMPILE
, um SQL Server zu zwingen, vorhandene Pläne zu ignorieren.OPTIMIZE
, weil Microsoft ein amerikanisches Unternehmen ist. :)Vergessen Sie nicht, dass die ANSI-Einstellungen, die Sie für den Verbindungsplan eingerichtet haben, eine Rolle bei der Auswahl des Ausführungsplans spielen. Wenn die App die gespeicherte Prozedur aufruft, hat sie wahrscheinlich andere ANSI-Einstellungen als Ihre SSMS-Verbindung.
quelle