Sql server 防止ADO.NET使用sp_executesql
在我们的SQL Server 2005数据库中(使用带有DBCC FREEPROCCACHE的Management Studio进行测试Sql server 防止ADO.NET使用sp_executesql,sql-server,ado.net,Sql Server,Ado.net,在我们的SQL Server 2005数据库中(使用带有DBCC FREEPROCCACHE的Management Studio进行测试 DBCC DROPCLEANBUFFERS),下面的语句速度很快(~0.2s编译时间,~0.1s执行时间): 但是,以下语句速度较慢(~0.2秒编译时间,7-11秒执行时间): SQL Server选择不同的执行计划,尽管查询相同。这是有意义的,因为在第一种情况下,SQL Server具有a、b的实际值和所有其他可用参数,并且可以使用统计信息创建更好的计划。显
DBCC DROPCLEANBUFFERS
),下面的语句速度很快(~0.2s编译时间,~0.1s执行时间):
但是,以下语句速度较慢(~0.2秒编译时间,7-11秒执行时间):
SQL Server选择不同的执行计划,尽管查询相同。这是有意义的,因为在第一种情况下,SQL Server具有a
、b
的实际值和所有其他可用参数,并且可以使用统计信息创建更好的计划。显然,参数的具体值的查询计划比一般的查询计划好得多,并且肯定超过了任何“查询计划缓存”的性能优势
现在我的问题是:ADO.NET在执行参数化查询时似乎总是使用第二个选项(sp_executesql),这通常是有意义的(查询计划缓存等)。然而,在我们的例子中,这会降低性能。那么,有什么办法可以做到这一点吗
- 强制ADO.NET使用不同于
(即SQL Server查询分析器考虑实际参数值的内容)或sp_executesql
- 在考虑参数值的情况下,是否强制SQL Server重新包含传递给sp_executesql的SQL的查询计划
sql=“WHERE b=“+quoteAndEscape(parameterB)
将SQL放入存储过程没有任何区别(慢速、带和不带以及重新编译)。我没有发布实际的SQL语句,因为它非常复杂(通过多个表进行连接,包括子选择和聚合)。您可以尝试使用which(引号):
指示查询优化器使用
局部变量的特定值
当查询被编译并
优化。仅使用该值
在查询优化期间,而不是
在查询执行期间。优化
可以抵消参数检测
优化器的行为或可以是
创建平面辅助线时使用
我认为这个问题与在数据库中使用VARCHAR
数据类型有关。如果where参数声明为NVARCHAR
,SQL Server似乎不会使用指定的索引
但是,您可以将数据库列更改为NVARCHAR
(这当然会增加大小),然后索引性能可能会提高
我目前在LINQ上遇到了这个问题,实际上可能需要恢复使用存储过程来解决这个问题
这个问题在我知道的旧帖子中有详细解释,但我只是通过谷歌搜索发现了几乎完全相同的短语!我遇到了完全相同的问题(查询在ManagementStudio中使用参数运行得非常快,但通过ADO.Net运行得非常慢),并通过“exec sp_execute”在ManagementStudio中运行查询来复制该问题。这两个执行计划非常不同,即使有Optimize for query提示,所以我所做的是将一些数据初始选择到一个临时表中。这似乎起到了作用,如果你说你的查询是一个复杂的查询,那么在你的案例中也可能起到作用-我不太确定它是如何工作的,但是,即使在使用sp_execute时,它似乎也能使执行计划正常运行。我会将查询移动到存储过程,然后在命令中指定command.CommandType=CommandType.StoredProcedure
这不会创建sp_executesql并提高性能将其转换为存储过程与临时查询一样慢?这是一种非常奇怪的行为,所以我必须问:你确定吗?@Rubens-你为什么这么说?与缓存、编译、参数化的临时查询相比,存储过程提供了什么性能优势?是的,我肯定。为什么要更快?编译时间与执行时间(7-11秒)相比微不足道(0.2秒)。@David,@Heinzi:我说的是因为查询执行计划(QEP)缓存@Rubens-对于临时查询也是这样,不是吗?这正是我们最终要做的:使用临时表(#…
)将查询拆分为较小的查询,以防止查询优化器选择非常糟糕的计划。当您在sql server中执行查询时,它与sp#U执行不同,sp_在sql server中执行缓存执行计划时不考虑任何参数。因此,对于应用的第一个参数,您的缓存执行计划可能足够好,但对于其他查询,它不是最佳的。为了确保您必须清除当前查询的缓存计划。这种问题被称为参数嗅探。在几个小时的阅读、嗅探参数问题、设置ARITHABORT参数等之后。。。这恰好是我的问题,我没有在查询中显式设置参数类型,它们被作为nvarchar传递,我在数据库中有varchar。谢谢
SELECT ... FROM ... WHERE a = 1 AND b = '' ...
exec sp_executesql N'SELECT ... FROM ... WHERE a = @a AND b = @b ...', N'@a int, @b nvarchar(4000), ...', @a=1, @b=N'', ...