与SqlCommand一起使用时,为什么某些sql查询要慢得多?

时间:2009-04-29 11:26:35

标签: .net sql sqlcommand

我有一个存储过程,从Sql Server Management Studio(2秒)执行的速度比使用System.Data.SqlClient.SqlCommand运行速度快得多(2分钟后超时)。

这可能是什么原因?


详细说明: 在Sql Server Management Studio中,它在2秒内运行(在生产数据库上):

EXEC sp_Stat
    @DepartmentID = NULL

在.NET / C#中,以下时间超过2分钟(在生产数据库上):

string selectCommand = @"
EXEC sp_Stat
    @DepartmentID = NULL";
string connectionString = "server=***;database=***;user id=***;pwd=***";
using (SqlConnection connection = new SqlConnection(connectionString))
{
    using (SqlCommand command = new SqlCommand(selectCommand, connection))
    {
        connection.Open();
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
            }
        }
    }
}

我也尝试使用selectCommand = "sp_Stat"CommandType = StoredProcedureSqlParameter,但结果相同。

没有EXEC,结果也是一样的。

在几乎数据空的开发数据库中,两个案例都在不到1秒的时间内完成。所以它与数据库中存在大量数据有关,但它似乎只发生在.NET ...


Marc Gravell撰写的关于不同SET值的文章在所呈现的案例中有所不同。

SQL Server Profiler显示Sql Server Management Studio运行.NET Sql客户端数据提供程序不支持的以下SET


SET ROWCOUNT 0 
SET TEXTSIZE 2147483647 
SET NOCOUNT OFF 
SET CONCAT_NULL_YIELDS_NULL ON 
SET ARITHABORT ON 
SET LOCK_TIMEOUT -1 
SET QUERY_GOVERNOR_COST_LIMIT 0 
SET DEADLOCK_PRIORITY NORMAL 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 
SET ANSI_NULLS ON 
SET ANSI_NULL_DFLT_ON ON 
SET ANSI_PADDING ON 
SET ANSI_WARNINGS ON 
SET CURSOR_CLOSE_ON_COMMIT OFF 
SET IMPLICIT_TRANSACTIONS OFF 
SET QUOTED_IDENTIFIER ON
SET NOEXEC, PARSEONLY, FMTONLY OFF

当我包含这些内容时,相同的查询在SSMS和.NET中花费了相同的时间。 责任人SET是......

SET ARITHABORT ON

我学到了什么?也许使用分析器而不是猜测......

(最初的解决方案似乎与参数嗅探有关。但我混淆了一些事情......)

4 个答案:

答案 0 :(得分:10)

另一件重要的事情是the SET options已启用。其中一些选项可以充分更改查询计划以更改配置文件。如果您正在查看(例如)计算的+持久(并且可能已编入索引)列,则有些会产生巨大影响:如果SET选项不兼容,则可以强制它重新计算值,而不是使用索引值 - 这可以将索引搜索更改为表扫描+计算。

尝试使用分析器查看“正在播放”的SET个选项,并查看是否使用这些选项更改了内容。

另一个影响是连接字符串;例如,如果启用可以微妙改变行为的MARS。

最后,事务(隐式(TransactionScope)或显式)可能会产生巨大的影响,具体取决于隔离级别。

答案 1 :(得分:5)

这几乎可以肯定是由于“不正确”的缓存查询计划。这已经出现了很多次。

您是否拥有最新统计数据?定期编制索引维护计划?

您可以通过将其添加到存储过程定义来测试是否肯定是由于缓存的查询计划:

CREATE PROCEDURE usp_MyProcedure WITH RECOMPILE...

这将重新索引整个数据库(如果数据库非常大,请注意!):

exec sp_msforeachtable "dbcc dbreindex('?')"

SO帖子:

Big difference in execution time of stored proc between Managment Studio and TableAdapter.

Parameter Sniffing (or Spoofing) in SQL Server

optimize for unknown for SQL Server 2005?

Different Execution Plan for the same Stored Procedure

答案 2 :(得分:1)

有一个类似的问题,结果是连接字符串中的MultipleActiveResultSets = true(应该具有最小的影响)是通过远程连接拉动1.5mil记录需要25分钟而不是大约2分钟。

答案 3 :(得分:0)

我们有一个类似的问题,在SSMS中查询将在2秒内完成,从.NET客户端调用时需要花费90秒以上(我们编写了几个VB / C#apps / sites来测试它。)

我们怀疑查询计划会有所不同,并使用显式循环(“内循环连接”和“带索引”)提示重写了查询。这解决了这个问题。