Ich habe zwei fast identische Abfragen, die auf derselben SQL Server 2005-Instanz ausgeführt werden:
- Die erste ist die ursprüngliche
SELECT
Abfrage, die von LINQ generiert wurde (ich weiß, ich weiß ... ich bin nicht der Anwendungsentwickler, nur der DBA :). - Der zweite ist genau der gleiche wie der erste, fügte ein
OPTION (RECOMPILE)
am Ende.
Sonst wurde nichts geändert.
Der erste dauert bei jedem Lauf 55 Sekunden.
Der zweite dauert 2 Sekunden.
Beide Ergebnismengen sind identisch.
Warum würde dieser Hinweis zu einem derart dramatischen Leistungszuwachs führen?
Der Eintrag in der RECOMPILE
Onlinedokumentation bietet keine ausführliche Erklärung:
Weist das SQL Server-Datenbankmodul an, den nach seiner Ausführung für die Abfrage generierten Plan zu verwerfen, und zwingt das Abfrageoptimierungsprogramm, einen Abfrageplan bei der nächsten Ausführung derselben Abfrage neu zu kompilieren. Ohne Angabe von RECOMPILE speichert das Datenbankmodul Abfragepläne im Cache und verwendet sie erneut. Beim Kompilieren von Abfrageplänen verwendet der Abfragehinweis RECOMPILE die aktuellen Werte aller lokalen Variablen in der Abfrage. Befindet sich die Abfrage in einer gespeicherten Prozedur, werden die aktuellen Werte an alle Parameter übergeben.
RECOMPILE ist eine nützliche Alternative zum Erstellen einer gespeicherten Prozedur, die die WITH RECOMPILE-Klausel verwendet, wenn nur eine Teilmenge von Abfragen innerhalb der gespeicherten Prozedur anstelle der gesamten gespeicherten Prozedur neu kompiliert werden muss. Weitere Informationen finden Sie unter Neukompilieren gespeicherter Prozeduren. RECOMPILE ist auch nützlich, wenn Sie Planhinweise erstellen. Weitere Informationen finden Sie unter Optimieren von Abfragen in bereitgestellten Anwendungen mithilfe von Plan-Handbüchern.
Da meine Abfrage viele lokale Variablen enthält, kann SQL Server sie vermutlich (ernsthaft) optimieren, wenn ich den OPTION (RECOMPILE)
Abfragehinweis verwende.
Überall, wo ich hinschaue, sagen die Leute, das OPTION (RECOMPILE)
sollte vermieden werden. Die Erklärung dafür ist im Allgemeinen, dass SQL Server mit diesem Hinweis diesen Exection-Plan nicht wiederverwenden kann und daher jedes Mal Zeit damit verschwenden muss, ihn neu zu kompilieren.
(Aber) Angesichts des gigantischen Leistungsvorteils bin ich der Meinung, dass die Verwendung dieses Abfragehinweises diesmal eine gute Sache wäre.
Soll ich es benutzen? Wenn nicht, gibt es eine Möglichkeit, SQL Server zu zwingen, einen besseren Ausführungsplan ohne diesen Hinweis und ohne Änderung der Anwendung zu verwenden?