sp_executesql何时刷新查询计划?


13

您必须原谅我的天真,因为我不是DBA,但我的理解是,随着时间的推移,必须重新编译数据库更改和存储过程的统计信息,以使查询计划与最新的统计信息保持最新。

假设我的数据库中有一个存储过程,可以按一定的时间间隔对最新的统计信息进行重新编译,那么将存储过程内联到代码中并将其包装在sp_executesql语句中的含义是什么?在重新编译过程的过程中,是否会丢失对查询计划的刷新?

如果在进行此更改之前我还有其他需要考虑的事项(权限除外),那么感谢您的见解。

我在MSDN上阅读过:

SQL Server查询优化器将新的Transact-SQL字符串与现有执行计划进行匹配的能力受到字符串文本中参数值不断变化的影响,特别是在复杂的Transact-SQL语句中。

因此,假设我尝试进行内联和包装的存储过程sp_executesql确实包含一些参数,这是否表示尽管我的执行计划已被缓存,但使SQL Server很难找到并重用它?

Answers:


7

来自MSDN的一行正在讨论using EXEC(),例如:

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

在我的测试中,现代版本的SQL Server仍然可以重用这样的计划,但是可能还有其他变量(例如版本,或者例如,如果您WHERE基于某些参数的存在添加条件子句-在这种情况下,会生成不同的计划)。

如果使用,sp_executesql则参数值仍然会导致参数嗅探问题(就像使用普通SQL一样),但这与SQL Server是否可以重用该计划无关。该计划将一遍又一遍地使用,就像您根本没有使用sp_executesql过一样,除非会导致直接查询重新编译的变量,在这种情况下,该计划也将被重新编译(本质上,SQL Server不会存储任何带有计划的计划,其中包括“这是从sp_executesql执行的,但不是):

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

另外,它具有针对动态SQL的内置保护,避免了由于字符串定界符而使您不必担心将单引号加倍。我在这里写了一些这样的博客

如果您有计划再利用和/或参数嗅探问题,有些事情你应该考虑是OPTION (RECOMPILE)OPTIMIZE FORoptimize for ad hoc workloadssimple/forced parameterization。为了回应这里最近的网络广播,我回答了一些类似的问题,可能值得一看:

http://sqlperformance.com/performance-palooza

要点是:不要害怕sp_executesql使用它,而仅在需要时使用它,而在遇到实际性能问题时才花费精力过度优化它。上面的例子很糟糕,因为这里没有理由使用动态SQL-我已经写了这个答案,假设您有合法的用例。


2

通过sp_executesql运行的查询与不通过sp_executesql运行的普通查询遵循相同的执行计划规则。如果查询文本更改,那么将创建一个新计划。如果由于使用参数而文本没有变化,则将重用该计划。统计信息更新后,计划到期,并且下次运行查询时将生成新计划。


感谢您的回答,我对参数进行了编辑,因为我现在意识到,每次调用sp_ExecuteSql时,由于从Sql Server的角度来看,我已替换了一个字符串,因此我将使用不同的字符串作为查询具有硬编码值的参数(在我将查询发送到Sql Server之前,它们将以代码形式输入)。您知道解决这个问题的方法吗?在嵌入式SQL语句中声明变量是否可以帮助查询优化器找到我的缓存查询计划?
詹姆斯·刘易斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.