【发布时间】:2011-01-03 17:32:56
【问题描述】:
在我们的 SQL Server 2005 数据库中(使用 Management Studio 和 DBCC FREEPROCCACHE 和
DBCC DROPCLEANBUFFERS),下面的语句很快(编译时间~0.2s,执行时间~0.1s):
SELECT ... FROM ... WHERE a = 1 AND b = '' ...
但是,以下语句很慢(编译时间约为 0.2 秒,执行时间 7-11 秒):
exec sp_executesql N'SELECT ... FROM ... WHERE a = @a AND b = @b ...', N'@a int, @b nvarchar(4000), ...', @a=1, @b=N'', ...
SQL Server 选择不同的执行计划,尽管查询是相同的。这是有道理的,因为在第一种情况下,SQL Server 具有a、b 和所有其他可用参数的实际值,并且可以使用统计信息来创建更好的计划。显然,针对参数具体值的查询计划比通用查询计划好得多,而且绝对超过任何“查询计划缓存”的性能优势。
现在我的问题是:ADO.NET 在执行参数化查询时似乎总是使用第二个选项 (sp_executesql),这 通常 是有意义的(查询计划缓存等)。然而,在我们的例子中,这会影响性能。那么,有没有办法呢
- 强制 ADO.NET 使用不同于
sp_executesql的东西(即 SQL Server 查询分析器将实际参数值考虑在内的东西)或 - 强制 SQL Server 重新计算传递给
sp_executesql的 SQL 的查询计划考虑参数值?
请不要告诉我我必须回到丑陋、古老、危险的sql = "WHERE b = " + quoteAndEscape(parameterB)...
将 SQL 放入存储过程中没有区别(慢,有和没有 WITH RECOMPILE)。我没有发布实际的 SQL 语句,因为它非常复杂(连接多个表,包括子 SELECT 和聚合)。
【问题讨论】:
-
将其转换为存储过程与即席查询一样慢?这是一个非常奇怪的行为,所以我必须问:你确定吗?
-
@Rubens - 你为什么这么说?与缓存、编译、参数化的即席查询相比,存储过程有哪些性能优势?
-
是的,我确定。为什么应该更快?与执行时间 (7-11s) 相比,编译时间 (0.2s) 微不足道。
-
@David, @Heinzi:我这么说是因为查询执行计划(QEP)缓存;
-
@Rubens - 你也得到了即席查询,不是吗?
标签: sql-server ado.net