Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 防止ADO.NET使用sp_executesql_Sql Server_Ado.net - Fatal编程技术网

Sql server 防止ADO.NET使用sp_executesql

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的实际值和所有其他可用参数,并且可以使用统计信息创建更好的计划。显

在我们的SQL Server 2005数据库中(使用带有DBCC FREEPROCCACHE的Management Studio进行测试
DBCC DROPCLEANBUFFERS
),下面的语句速度很快(~0.2s编译时间,~0.1s执行时间):

但是,以下语句速度较慢(~0.2秒编译时间,7-11秒执行时间):

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放入存储过程没有任何区别(慢速、带和不带
以及重新编译)。我没有发布实际的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'', ...