簡體   English   中英

在代碼中查詢極慢但在 SSMS 中查詢速度很快

[英]Query extremely slow in code but fast in 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 rows ,而es_history_dt包含8588493 rows 這兩個表都有很好的索引,並且 SSMS 中的執行計划表示它們正在使用索引查找進行查找,因此它們是快速查找。 該程序的行為就好像它沒有使用 C# 版本的查詢的索引。

您在 SSMS 中的代碼與您在應用程序中運行的代碼不同。 應用程序中的這一行添加了一個 NVARCHAR 參數:

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

在 SSMS 腳本中,您將其聲明為 VARCHAR:

declare @clientID varchar(200)

由於數據類型優先級的規則,查詢中的Where client_id = @clientID表達式在@clientID的類型為 NVARCHAR 的情況下不支持 SARG(我正在做出信念的飛躍,並假設client_id列的類型為 VARCHAR)。 因此,應用程序強制執行表掃描,SSMS 查詢可以在其中進行快速鍵搜索。 這是使用Parameters.AddWithValue 的一個眾所周知和理解的問題,之前已經在許多文章中討論過,例如。 請參閱數據訪問代碼如何影響數據庫性能 一旦理解了問題,解決方案就很簡單了:

第一個解決方案是優越的,因為它除了解決 SARG 能力問題之外,還解決了緩存污染問題。

我還建議您閱讀應用程序中的慢速,SSMS 中的快速? 了解性能奧秘

按照此處的建議運行DBCC FREEPROCCACHE ,以確保問題不是由於過時的查詢執行計划造成的。

有同樣的問題:

  • 從代碼調用存儲過程:30 秒+
  • 從 SSMS 調用相同的存儲過程:毫秒。
  • 從代碼中的存儲過程中調用 SQL:毫秒。

解決方案:刪除存儲過程,然后重新創建完全相同的存儲過程,現在都以毫秒為單位返回。 沒有代碼更改。

原因:請有人提出這個修復會產生影響的原因?

在您的 c# 連接上運行探查器 - 可能還有其他您不知道的活動正在進行。

手動運行查詢時從 SSMS 中捕獲執行計划,然后在運行應用程序時從 Profiler 中捕獲執行計划。 比較和對比。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM