在代码中查询非常慢,但在 SSMS 中查询速度很快

发布于 2024-12-07 13:16:24 字数 1842 浏览 0 评论 0 原文

我有一个相当简单的查询,当它在代码中运行时,我不断超时(需要三分钟多才能完成,我提前停止了它,所以我可以发布这个问题),但是当我从同一台计算机运行相同的查询时在 Sql Server Management Studio 中,当数据未缓存在服务器上时,第一次查询仅需要 2532 毫秒,而重复查询则需要 524 毫秒

这是我的 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# 版本查询的索引。

I have a fairly simple query that I keep getting timeouts (it takes over three minutes to complete, I stopped it early so I could post this question) on when it is running in code, however when I run the same query from the same computer in Sql Server Management Studio the query will only take 2532 ms the first query when the data is not cached on the server and 524 ms for repeated queries.

Here is my c# code

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.
}

here is my code I am running in SSMS, I pulled it right from 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

What is causing the major discrepancy for the difference in time?


To keep the comment section clean, I will answer some FAQ's here.

The same computer and logon is used for both the application and ssms.

Only 15 rows are returned in my example query. However, es_history contains 11351699 rows and es_history_dt contains 8588493 rows. Both tables are well indexed and the execution plan in SSMS says they are using index seeks for the look-ups so they are fast lookups. The program is behaving as if it is not using the indexes for the C# version of the query.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

み零 2024-12-14 13:16:24

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

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

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

declare @clientID varchar(200)

由于 数据类型优先级 查询中的 Where client_id = @clientID 表达式不支持 SARG,其中 @clientID 为类型 NVARCHAR(我的信念飞跃并假设 client_id 列的类型为 VARCHAR)。因此,应用程序强制进行表扫描,其中 SSMS 查询可以执行快速键查找。这是使用Parameters.AddWithValue 时众所周知且易于理解的问题,并且之前已在许多文章中讨论过,例如。请参阅数据访问代码如何影响数据库性能。一旦理解了问题,解决方案就很简单:

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

我还建议您阅读应用程序慢,SSMS 快?了解性能奥秘

Your code in SSMS is not the same code you run in your application. This line in your application adds a NVARCHAR parameter:

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

while in the SSMS script you declare it as VARCHAR:

declare @clientID varchar(200)

Due to the rules of Data Type Precedence the Where client_id = @clientID expression in your query is not SARG-able where @clientID is of type NVARCHAR (I'm making a leap of faith and assume that client_id column is of type VARCHAR). The application thus forces a table scan where the SSMS query can do a quick key seek. This is a well know and understood issue with using Parameters.AddWithValue and has been discussed in many articles before, eg. see How Data Access Code Affects Database Performance. Once the problem is understood, the solutions are trivial:

The first solution is superior because it solves the cache pollution problem in addition to the SARG-ability problem.

I would also recommend you read Slow in the Application, Fast in SSMS? Understanding Performance Mysteries

晨光如昨 2024-12-14 13:16:24

按照建议运行DBCC FREEPROCCACHE这里,只是为了确保问题不是由于过时的查询执行计划造成的。

Run DBCC FREEPROCCACHE, as suggested here, just to make sure the problem isn't due to a stale query execution plan.

追星践月 2024-12-14 13:16:24

遇到同样的问题:

  • 从代码调用存储过程:30 秒+
  • 从 SSMS 调用相同存储过程:毫秒。
  • 从代码中的存储过程中调用 SQL:毫秒。

解决方案
删除存储过程,然后重新创建完全相同的存储过程,现在两者都以毫秒为单位返回。没有代码更改。

Had the same issue:

  • Call Stored procedure from code: 30 seconds+
  • Call Same Stored procedure from SSMS: milliseconds.
  • Call SQL from within stored procedure from code: milliseconds.

Solution:
Drop Stored Procedure, then recreate exactly the same stored procedure, now both returning in milliseconds. No code change.

征﹌骨岁月お 2024-12-14 13:16:24

在您的 C# 连接上运行探查器 - 可能还有您不知道的其他活动正在发生。

Run the profiler on your c# connection - there may be other activity going on that you are not aware of.

痴情换悲伤 2024-12-14 13:16:24

当您手动运行查询时,从 SSMS 捕获执行计划;当您运行应用程序时,从 Profiler 捕获执行计划。比较和对比。

Capture the execution plan from both SSMS when you manually run your query and then from Profiler when you are running your application. Compare and contrast.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文