Wann aktualisiert sp_executesql den Abfrageplan?

13

Sie müssen mir meine Naivität verzeihen, da ich kein DBA bin. Meines Wissens nach müssen die Statistiken einer Datenbankänderung und einer gespeicherten Prozedur im Laufe der Zeit neu kompiliert werden, um den Abfrageplan mit den neuesten Statistiken auf dem neuesten Stand zu halten.

Angenommen , ich habe eine gespeicherte Prozedur in der Datenbank , die gegen die neuesten Statistiken auf neu kompiliert wird einige regelmäßigen Abständen, was sind die Auswirkungen der gespeicherten Prozedur in Code in-Futter und es in einer Verpackung sp_executesqlAussage? Verliere ich die Aktualisierung des Abfrageplans, die im Rahmen der Neukompilierung der Prozedur durchgeführt wurde?

Wenn ich noch etwas anderes (außer Berechtigungen) berücksichtigen muss, bevor ich diese Änderung vornehme, würde ich mich über Ihre Erkenntnisse freuen.

Ich habe dies auf MSDN gelesen:

Die Fähigkeit des SQL Server-Abfrageoptimierers, die neue Transact-SQL-Zeichenfolge mit einem vorhandenen Ausführungsplan abzugleichen, wird durch die sich ständig ändernden Parameterwerte im Text der Zeichenfolge beeinträchtigt, insbesondere bei komplexen Transact-SQL-Anweisungen.

Unter der Annahme, dass die gespeicherte Prozedur, die ich in die Zeile einbinden und einbinden sp_executesqlmöchte, tatsächlich einige Parameter enthält, bedeutet dies, dass es für SQL Server schwieriger ist, sie zu finden und wiederzuverwenden, obwohl mein Ausführungsplan zwischengespeichert ist?

James Lewis
quelle

Antworten:

7

Die Zeile von MSDN spricht über die Verwendung von EXEC(), wie folgt :

SET @sql = 'SELECT foo FROM dbo.bar WHERE x = ''' + @x + ''';';
EXEC(@sql);

In meinen Tests können moderne Versionen von SQL Server einen Plan wie diesen immer noch wiederverwenden, es können jedoch auch andere Variablen vorhanden sein (z. B. version, oder wenn Sie Bedingungsklauseln hinzufügen WHERE, die auf dem Vorhandensein bestimmter Parameter basieren - in diesem Fall einen anderen Plan erstellen).

Wenn Sie verwenden sp_executesql, können die Parameterwerte (wie bei normalem SQL) immer noch Probleme mit dem Parameter-Sniffing verursachen. Dies hat jedoch nichts damit zu tun, ob SQL Server den Plan wiederverwenden kann. Dieser Plan wird immer wieder verwendet, so als ob Sie ihn überhaupt nicht verwendet hätten sp_executesql, es sei denn, Variablen, die eine direkte Abfrage veranlassen würden, werden neu kompiliert. In diesem Fall wird auch diese neu kompiliert (SQL Server im Wesentlichen nicht) Speichern Sie alles mit dem Plan, der besagt, dass "dies von sp_executesql ausgeführt wurde, dies aber nicht):

SET @sql = N'SELECT foo FROM dbo.bar WHERE x = @x;';
EXEC sp_executesql @sql, N'@x VARCHAR(32)', @x;

Als Bonus bietet dies einen integrierten Schutz gegen dynamisches SQL und vermeidet, dass Sie sich wegen Zeichenfolgenbegrenzern Gedanken über das Verdoppeln von einfachen Anführungszeichen machen müssen. Darüber habe ich hier einiges gebloggt .

Wenn Sie Probleme mit Plan wiederverwendet werden und / oder Parameter Sniffing, einige Dinge , die Sie achten sollten in sind OPTION (RECOMPILE), OPTIMIZE FOR, optimize for ad hoc workloadsund simple/forced parameterization. Ich habe einige ähnliche Fragen in Beantwortung eines aktuellen Webcasts hier angesprochen. Es kann sich lohnen, einen Blick darauf zu werfen:

http://sqlperformance.com/performance-palooza

Das Wesentliche ist: Haben Sie keine Angst, es zu verwenden sp_executesql, sondern verwenden Sie es nur, wenn Sie es benötigen, und verwenden Sie Energie, um es zu optimieren, wenn Sie ein tatsächliches Leistungsproblem haben. Das obige Beispiel ist furchtbar, da es hier keinen Grund gibt, dynamisches SQL zu verwenden - ich habe diese Antwort unter der Annahme geschrieben, dass Sie einen legitimen Anwendungsfall haben.

Aaron Bertrand
quelle
2

Die Abfragen, die über sp_executesql ausgeführt werden, folgen denselben Regeln für Ausführungspläne wie normale Abfragen, die nicht über sp_executesql ausgeführt werden. Wenn sich der Abfragetext ändert, wird ein neuer Plan erstellt. Wenn sich der Text aufgrund des Benutzers von Parametern nicht ändert, wird der Plan erneut verwendet. Wenn die Statistiken aktualisiert werden, laufen die Pläne ab, und beim nächsten Ausführen der Abfrage werden neue Pläne generiert.

mrdenny
quelle
Vielen Dank für Ihre Antwort, ich habe eine Änderung in Bezug auf Parameter vorgenommen, da mir jetzt klar geworden ist, dass ich bei jedem Aufruf von sp_ExecuteSql eine andere Zeichenfolge als Abfrage verwende, da ich aus Sicht von Sql Server ersetzt habe die Parameter mit fest codierten Werten (sie werden im Code eingegeben, bevor ich meine Anfrage an SQL Server sende). Kennen Sie einen Weg, um dies zu umgehen? Würde das Deklarieren von Variablen in meiner Inline-SQL-Anweisung dem Abfrageoptimierer dabei helfen, meinen zwischengespeicherten Abfrageplan zu finden?
James Lewis