Ich bin auf eine seltsame Situation gestoßen, in der das Anhängen OPTION (RECOMPILE)
an meine Abfrage dazu führt, dass sie in einer halben Sekunde ausgeführt wird. Wenn Sie sie weglassen, dauert die Abfrage weit über fünf Minuten.
Dies ist der Fall, wenn die Abfrage von Query Analyzer oder von meinem C # -Programm über ausgeführt wird SqlCommand.ExecuteReader()
. Anrufen (oder nicht anrufen) DBCC FREEPROCCACHE
oder DBCC dropcleanbuffers
macht keinen Unterschied; Abfrageergebnisse werden immer sofort mit OPTION (RECOMPILE)
und länger als fünf Minuten ohne zurückgegeben. Die Abfrage wird immer mit denselben Parametern aufgerufen [für diesen Test].
Ich verwende SQL Server 2008.
Ich bin ziemlich OPTION
vertraut mit dem Schreiben von SQL, habe aber noch nie zuvor einen Befehl in einer Abfrage verwendet und war mit dem gesamten Konzept der Plan-Caches bis zum Scannen der Beiträge in diesem Forum nicht vertraut. Mein Verständnis aus den Beiträgen ist, dass dies OPTION (RECOMPILE)
eine teure Operation ist. Es wird anscheinend eine neue Suchstrategie für die Abfrage erstellt. Warum sind nachfolgende Abfragen, bei denen das weggelassen OPTION (RECOMPILE)
wird, so langsam? Sollten die nachfolgenden Abfragen nicht die Suchstrategie verwenden, die beim vorherigen Aufruf berechnet wurde und den Hinweis zur Neukompilierung enthielt?
Ist es höchst ungewöhnlich, eine Abfrage zu haben, die bei jedem einzelnen Aufruf einen Neukompilierungshinweis erfordert?
Entschuldigen Sie die Einstiegsfrage, aber ich kann nicht wirklich Kopf oder Zahl daraus machen.
UPDATE: Ich wurde gebeten, die Anfrage zu stellen ...
select acctNo,min(date) earliestDate
from(
select acctNo,tradeDate as date
from datafeed_trans
where feedid=@feedID and feedDate=@feedDate
union
select acctNo,feedDate as date
from datafeed_money
where feedid=@feedID and feedDate=@feedDate
union
select acctNo,feedDate as date
from datafeed_jnl
where feedid=@feedID and feedDate=@feedDate
)t1
group by t1.acctNo
OPTION(RECOMPILE)
Wenn ich den Test mit Query Analyzer ausführe, stelle ich die folgenden Zeilen voran:
declare @feedID int
select @feedID=20
declare @feedDate datetime
select @feedDate='1/2/2009'
Beim Aufruf von meinem C # -Programm werden die Parameter über die SqlCommand.Parameters
Eigenschaft übergeben.
Für die Zwecke dieser Diskussion können Sie davon ausgehen, dass sich die Parameter niemals ändern, sodass wir einen suboptimalen Parametergeruch als Ursache ausschließen können.
quelle
X = @X OR @X IS NULL
zuX=@X
und Durchführung einer Such Sehen hier oder Prädikate weiter nach unten gegen eine Ansicht mit Fensterfunktionen drückenRECOMPILE
. Erfassen Sie auf jeden Fall die Ausführungspläne und sehen Sie sich die Unterschiede an.Antworten:
Es gibt Zeiten, in denen
OPTION(RECOMPILE)
die Verwendung Sinn macht. Nach meiner Erfahrung ist dies nur dann sinnvoll, wenn Sie dynamisches SQL verwenden. Bevor Sie untersuchen, ob dies in Ihrer Situation sinnvoll ist, würde ich empfehlen, Ihre Statistiken neu zu erstellen. Dies kann durch Ausführen der folgenden Schritte erfolgen:Und dann erstellen Sie Ihren Ausführungsplan neu. Dadurch wird sichergestellt, dass bei der Erstellung Ihres Ausführungsplans die neuesten Informationen verwendet werden.
Hinzufügen
OPTION(RECOMPILE)
der Ausführungsplan jedes Mal neu erstellt, wenn Ihre Abfrage ausgeführt wird. Ich habe das noch nie gehört,creates a new lookup strategy
aber vielleicht verwenden wir nur unterschiedliche Begriffe für dieselbe Sache.Wenn eine gespeicherte Prozedur erstellt wird (ich vermute, Sie rufen Ad-hoc-SQL aus .NET auf, aber wenn Sie eine parametrisierte Abfrage verwenden, handelt es sich letztendlich um einen gespeicherten Proc-Aufruf ), versucht SQL Server, den effektivsten Ausführungsplan für diese Abfrage zu ermitteln basierend auf den Daten in Ihrer Datenbank und den übergebenen Parametern ( Parameter-Sniffing ) und diesen Plan dann zwischen. Dies bedeutet, dass der zwischengespeicherte Ausführungsplan möglicherweise nicht mehr der effektivste ist, wenn Sie die Abfrage erstellen, in der sich 10 Datensätze in Ihrer Datenbank befinden, und diese dann ausführen, wenn 100.000.000 Datensätze vorhanden sind.
Zusammenfassend - ich sehe keinen Grund dafür
OPTION(RECOMPILE)
der hier von Vorteil wäre. Ich vermute, Sie müssen nur Ihre Statistiken und Ihren Ausführungsplan aktualisieren. Das Wiederherstellen von Statistiken kann je nach Ihrer Situation ein wesentlicher Bestandteil der DBA-Arbeit sein. Wenn Sie nach der Aktualisierung Ihrer Statistiken immer noch Probleme haben, würde ich empfehlen, beide Ausführungspläne zu veröffentlichen.Und um Ihre Frage zu beantworten: Ja, ich würde sagen, es ist höchst ungewöhnlich, dass Ihre beste Option darin besteht, den Ausführungsplan jedes Mal neu zu kompilieren, wenn Sie die Abfrage ausführen.
quelle
OPTION (RECOMPILE)
Lösung die einzige zu sein.Wenn es einen drastischen Unterschied zwischen Ausführungen einer Abfrage gibt, stelle ich häufig fest, dass dies oft eines von fünf Problemen ist.
STATISTIKEN- Statistiken sind veraltet. Eine Datenbank speichert Statistiken über den Bereich und die Verteilung der Wertetypen in verschiedenen Spalten in Tabellen und Indizes. Dies hilft der Abfrage-Engine, einen "Angriffsplan" für die Ausführung der Abfrage zu entwickeln, z. B. die Art der Methode, mit der Schlüssel mithilfe eines Hashs zwischen Tabellen abgeglichen werden oder die gesamte Gruppe durchsucht wird. Sie können Update Statistics für die gesamte Datenbank oder nur für bestimmte Tabellen oder Indizes aufrufen. Dies verlangsamt die Abfrage von einem Lauf zum anderen, da bei veralteten Statistiken der Abfrageplan wahrscheinlich nicht optimal für die neu eingefügten oder geänderten Daten für dieselbe Abfrage ist (mehr dazu weiter unten). Es ist möglicherweise nicht richtig, Statistiken sofort in einer Produktionsdatenbank zu aktualisieren, da je nach Datenmenge, die abgetastet werden soll, ein gewisser Overhead, eine Verlangsamung und eine Verzögerung auftreten. Sie können auch einen vollständigen Scan oder eine Stichprobe verwenden, um die Statistiken zu aktualisieren. Wenn Sie sich den Abfrageplan ansehen, können Sie mit dem Befehl auch die Statistiken zu den verwendeten Indizes anzeigenDBCC SHOW_STATISTICS (Tabellenname, Indexname) . Dies zeigt Ihnen die Verteilung und Bereiche der Schlüssel, auf denen der Abfrageplan seinen Ansatz basiert.
PARAMETER-SNIFFING - Der zwischengespeicherte Abfrageplan ist für die bestimmten Parameter, die Sie übergeben, nicht optimal, obwohl sich die Abfrage selbst nicht geändert hat. Wenn Sie beispielsweise einen Parameter übergeben, der nur 10 von 1.000.000 Zeilen abruft, verwendet der erstellte Abfrageplan möglicherweise einen Hash-Join. Wenn der übergebene Parameter jedoch 750.000 der 1.000.000 Zeilen verwendet, ist der erstellte Plan möglicherweise ein Index- oder Tabellenscan. In einer solchen Situation können Sie die SQL-Anweisung anweisen, die Option OPTION (RECOMPILE) oder einen SP mit WITH RECOMPILE zu verwenden. Um der Engine mitzuteilen, dass es sich um einen "Einwegplan" handelt, und um keinen zwischengespeicherten Plan zu verwenden, der wahrscheinlich nicht gilt. Es gibt keine Regel, wie diese Entscheidung getroffen werden soll. Es hängt davon ab, wie die Abfrage von den Benutzern verwendet wird.
INDEXE - Möglicherweise hat sich die Abfrage nicht geändert, aber eine Änderung an anderer Stelle, z. B. das Entfernen eines sehr nützlichen Index, hat die Abfrage verlangsamt.
REIHEN GEÄNDERT - Die Zeilen, die Sie abfragen, ändern sich drastisch von Anruf zu Anruf. Normalerweise werden Statistiken in diesen Fällen automatisch aktualisiert. Wenn Sie jedoch dynamisches SQL erstellen oder SQL innerhalb einer engen Schleife aufrufen, besteht die Möglichkeit, dass Sie einen veralteten Abfrageplan verwenden, der auf der falschen drastischen Anzahl von Zeilen oder Statistiken basiert. Auch in diesem Fall ist OPTION (RECOMPILE) nützlich.
DIE LOGIK Es ist die Logik, Ihre Abfrage ist nicht mehr effizient, es war in Ordnung für eine kleine Anzahl von Zeilen, aber nicht mehr skalierbar. Dies beinhaltet normalerweise eine eingehendere Analyse des Abfrageplans. Zum Beispiel können Sie nicht mehr in großen Mengen arbeiten, sondern müssen Dinge aufteilen und kleinere Commits ausführen, oder Ihr Cross Product war für einen kleineren Satz in Ordnung, beansprucht jetzt jedoch CPU und Speicher, da es größer skaliert. Dies gilt möglicherweise auch für Mit DISTINCT rufen Sie für jede Zeile eine Funktion auf. Ihre Schlüsselübereinstimmungen verwenden aufgrund der CASTING-Typkonvertierung oder NULLS oder Funktionen keinen Index. Zu viele Möglichkeiten hier.
Wenn Sie eine Abfrage schreiben, sollten Sie sich im Allgemeinen ein Bild davon machen, wie bestimmte Daten in Ihrer Tabelle verteilt sind. Eine Spalte kann beispielsweise eine gleichmäßig verteilte Anzahl unterschiedlicher Werte aufweisen oder verzerrt sein. In 80% der Fälle gibt es einen bestimmten Satz von Werten, unabhängig davon, ob die Verteilung im Laufe der Zeit häufig variiert oder ziemlich statisch ist. Auf diese Weise erhalten Sie eine bessere Vorstellung davon, wie Sie eine effiziente Abfrage erstellen. Aber auch beim Debuggen haben die Abfrageleistungen eine Grundlage für die Erstellung einer Hypothese, warum sie langsam oder ineffizient ist.
quelle
Um der ausgezeichneten Liste (von @CodeCowboyOrg) Situationen hinzuzufügen, in denen OPTION (RECOMPILE) sehr hilfreich sein kann,
quelle
Die allererste Aktion vor dem Optimieren von Abfragen besteht darin, die Indizes und Statistiken zu defragmentieren / neu zu erstellen. Andernfalls verschwenden Sie Ihre Zeit.
Sie müssen den Ausführungsplan überprüfen, um festzustellen, ob er stabil ist (ist dasselbe, wenn Sie die Parameter ändern). Andernfalls müssen Sie möglicherweise einen Deckungsindex erstellen (in diesem Fall für jede Tabelle) (in Kenntnis des Systems können Sie einen solchen Index erstellen ist auch für andere Abfragen nützlich).
Als Beispiel: Index erstellen idx01_datafeed_trans On datafeed_trans (feedid, feedDate) INCLUDE (acctNo, tradeDate)
Wenn der Plan stabil ist oder Sie ihn stabilisieren können, können Sie den Satz mit sp_executesql ('SQL-Satz') ausführen, um einen festen Ausführungsplan zu speichern und zu verwenden.
Wenn der Plan instabil ist, müssen Sie jedes Mal eine Ad-hoc-Anweisung oder EXEC ('SQL-Satz') verwenden, um einen Ausführungsplan auszuwerten und zu erstellen. (oder eine gespeicherte Prozedur "mit Neukompilierung").
Ich hoffe es hilft.
quelle
Necroing diese Frage, aber es gibt eine Erklärung, die niemand in Betracht gezogen zu haben scheint.
STATISTIKEN - Statistiken sind nicht verfügbar oder irreführend
Wenn alle der folgenden Aussagen zutreffen:
Dann geht der SQL Server möglicherweise fälschlicherweise davon aus, dass die Spalten nicht korreliert sind, was zu niedrigeren als erwarteten Kardinalitätsschätzungen für die Anwendung beider Einschränkungen und der Auswahl eines schlechten Ausführungsplans führt. In diesem Fall besteht die Lösung darin, ein Statistikobjekt zu erstellen, das die beiden Spalten verbindet. Dies ist keine teure Operation.
quelle