Großer Unterschied in der Ausführungszeit zwischen Abfragen bei Verwendung des RECOMPILE-Abfragehinweises

16

Ich habe zwei fast identische Abfragen, die auf derselben SQL Server 2005-Instanz ausgeführt werden:

  1. Die erste ist die ursprüngliche SELECTAbfrage, die von LINQ generiert wurde (ich weiß, ich weiß ... ich bin nicht der Anwendungsentwickler, nur der DBA :).
  2. 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 RECOMPILEOnlinedokumentation 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?

ivanmp
quelle

Antworten:

16

Wie im Artikel Vom Abfrageoptimierer in Microsoft SQL Server 2005 verwendete Statistiken dokumentiert

Wenn Sie eine lokale Variable in einem Abfrageprädikat anstelle eines Parameters oder Literal verwenden, verwendet das Optimierungsprogramm eine Schätzung mit verringerter Qualität oder eine Schätzung der Selektivität des Prädikats. Verwenden Sie in der Abfrage Parameter oder Literale anstelle von lokalen Variablen

Wenn das Optimierungsprogramm überhaupt keine verwendbaren Statistiken für eine Spalte hat, wird davon ausgegangen, dass ein =Prädikat 10% der Zeilen, BETWEEN9% und eines von >, >=, < and <=30% entspricht. Wenn Spaltenstatistiken verfügbar sind, wird ein =Prädikat wie folgt anders behandelt.

Selbst wenn in einer Abfrage lokale Variablen verwendet werden, wird bei Gleichheitsprädikaten eine Schätzung verwendet, die besser ist als eine Schätzung. Die Selektivität für Bedingungen der Form " @local_variable = column_name" wird unter Verwendung der Durchschnittswerthäufigkeit aus dem Histogramm für Spaltenname geschätzt. Wenn die Spalte spaltenname beispielsweise alle eindeutigen Werte enthält 1/(number of unique values in column), wird eine genaue Selektivitätsschätzung von verwendet.

Das ist also im Wesentlichen dasselbe wie mit für OPTIMIZE FOR (UNKNOWN). Es ist zwar genauer als eine Pauschalschätzung, 10%aber nicht auf die von Ihnen abgefragten Werte zugeschnitten.

Fügen Sie der RECOMPILEAbfrage den Abfrage-Hinweis hinzu, um SQL Server zu zwingen, eine Abfrage bei jeder Ausführung zu optimieren, und die Werte lokaler Variablen zu verwenden, um die Kardinalität und die Kosten während der Optimierung der Abfrage zu schätzen .

Mit der Verwendung von erhalten RECOMPILESie vermutlich genauere Kardinalitätsschätzungen und daher einen anderen Plan mit Verknüpfungsaufträgen / Verknüpfungsarten, der der Anzahl der von verschiedenen Teilen Ihrer tatsächlichen Abfrage zurückgegebenen Zeilen besser entspricht.

Martin Smith
quelle