c# – 在SSMS中查询代码速度非常慢但快速

我有一个相当简单的查询,我不断得到超时(完成需要三分钟,我早点停止,所以我可以发布这个问题),当它运行在代码,但是当我运行相同的查询从同一台电脑在Sql Server Management Studio中,当服务器上没有缓存数据时,查询将只需要2532 ms的第一个查询,而对于重复的查询,查询将仅为524 ms。

这是我的c#代码

using (var conn = new SqlConnection("Data Source=backend.example.com;Connect Timeout=5;Initial Catalog=Logs;Persist Security Info=True;User ID=backendAPI;Password=Redacted"))
                using (var ada = new SqlDataAdapter(String.Format(@"
SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 {0}) {1}
Order by dt desc"
     , where.ToString(), (cbShowOnlyFailed.Checked ? "and Status = 1" : "")), conn))
{
    ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID);
    ada.SelectCommand.Parameters.AddWithValue("@dt", dtpFilter.Value);
    //ada.SelectCommand.CommandTimeout = 60;
    conn.Open();
    Logs.Clear();
    ada.Fill(Logs); //Time out exception for 30 sec limit.
}

这是我在SSMS中运行的代码,我从ada.SelectCommand.CommandText中直接拉出来

declare @clientID varchar(200)
set @clientID = '138'
declare @dt datetime
set @dt = '9/19/2011 12:00:00 AM'

SELECT [PK_JOB],[CLIENT_ID],[STATUS],[LOG_NAME],dt 
FROM [ES_HISTORY] 
inner join [es_history_dt] on [PK_JOB] = [es_historyid] 
Where client_id = @clientID and dt > @dt and (job_type > 4 or job_type = 0 or job_type = 1 or job_type = 4 ) 
Order by dt desc

导致时差的重大差异是什么?

为了保持评论部分的清洁,我将在这里回答一些常见问题。

同样的计算机和登录都用于应用程序和ssms。

在我的示例查询中只返回15行。但是,es_history包含11351699行,es_history_dt包含8588493行。两个表都很好地编入索引,SSMS中的执行计划表示他们正在使用索引查找查找,以便快速查找。该程序的行为就好像没有使用C#版本的查询的索引。

您在SSMS中的代码与应用程序中运行的代码不同。应用程序中的这一行添加了一个NVARCHAR参数:

 ada.SelectCommand.Parameters.AddWithValue("@clientID", ClientID);

而在SSMS脚本中,您将其声明为VARCHAR:

declare @clientID varchar(200)

由于Data Type Precedence的规则,您的查询中的client_id = @clientID表达式不是SARG能力,其中@clientID类型为NVARCHAR(我正在进行一个信念的飞跃,并假定client_id列的类型为VARCHAR)。因此,应用程序强制执行表扫描,SSMS查询可以在其中进行快速查找。这是使用Parameters.AddWithValue的一个很好的知道和理解的问题,并且已经在许多文章中讨论过,例如。见How Data Access Code Affects Database Performance.一旦问题被理解,解决方案是微不足道的:

>添加参数与constructor that accepts a type:Parameters.Add(“@ clientID”,SqlDbType.Varchar,200)(并做明确的长度,以防止缓存污染,参见Query performance and plan cache issues when parameter length not specified correctly
>或者在SQL文本中转换参数:其中client_id = cast(@clientID为varchar(200))。

第一个解决方案是优越的,因为它解决了除了SARG能力问题之外的缓存污染问题。

我也建议你阅读Slow in the Application, Fast in SSMS? Understanding Performance Mysteries

翻译自:https://stackoverflow.com/questions/7637907/query-extremely-slow-in-code-but-fast-in-ssms

转载注明原文:c# – 在SSMS中查询代码速度非常慢但快速