2008-10-30 138 views
30

爲什麼存儲過程返回一個包含9列的表,使用此代碼的89行需要60秒才能執行(.NET 1.1),這需要在SQL Server Management Studio中運行1秒鐘的時間?它被在本地機器上運行,因此很少/沒有網絡延遲,快速dev的機器SqlDataAdapter.Fill方法緩慢

Dim command As SqlCommand = New SqlCommand(procName, CreateConnection()) 
command.CommandType = CommandType.StoredProcedure 
command.CommandTimeout = _commandTimeOut 
Try 
    Dim adapter As new SqlDataAdapter(command) 
    Dim i as Integer 
    For i=0 to parameters.Length-1 
     command.Parameters.Add(parameters(i)) 
    Next 
    adapter.Fill(tableToFill) 
    adapter.Dispose() 
Finally 
    command.Dispose() 
End Try 

我放慢參數數組類型(對於此SQL,這只是一個參數)

parameters(0) = New SqlParameter("@UserID", SqlDbType.BigInt, 0, ParameterDirection.Input, True, 19, 0, "", DataRowVersion.Current, userID) 

存儲的過程只喜歡一個select語句這樣:

ALTER PROC [dbo].[web_GetMyStuffFool] 
    (@UserID BIGINT) 
AS 
SELECT Col1, Col2, Col3, Col3, Col3, Col3, Col3, Col3, Col3 
FROM [Table] 
+0

這是一個古老的問題,許多人找到它。在開始清理緩存並使用ARITHABORT設置進行遊戲之前,請閱讀Erland Sommarskog的綜合文章,該文章解釋了可能發生的情況:[緩慢的應用程序,SSMS中的快速?瞭解性能之謎](http://www.sommarskog.se/query-plan-mysteries.html)很多時候,這種行爲是由稱爲「參數嗅探」的SQL Server功能引起的。 – 2016-05-26 23:59:07

回答

45

首先,確保您正確分析性能。例如,從ADO.NET運行查詢兩次,查看第二次是否比第一次快得多。這消除了等待應用程序編譯和調試基礎架構增加的開銷。

接下來,檢查ADO.NET和SSMS中的默認設置。例如,如果您在SSMS中運行SET ARITHABORT OFF,則可能會發現它現在運行速度與使用ADO.NET時相比較慢。

我發現一次是SSMS中的SET ARITHABORT OFF導致存儲過程被重新編譯和/或使用不同的統計數據。突然,SSMS和ADO.NET報告的執行時間大致相同。

要檢查這一點,請查看每次運行的執行計劃,尤其是syscacheobjects表。他們可能會有所不同。

在特定的存儲過程上運行'sp_recompile'將從緩存中刪除相關的執行計劃,這使SQL Server有機會在下一次執行過程時創建一個可能更合適的計劃。

最後,你可以使用SSMS嘗試清理整個過程高速緩存和內存緩衝區的「nuke it from orbit」的方法:

DBCC DROPCLEANBUFFERS 
DBCC FREEPROCCACHE 

這樣做你測試你的查詢之前,防止高速緩存的執行計劃和之前的結果用法緩存。

+2

DBCC DROPCLEANBUFFERSDBCC FREEPROCCACHE解決了我的問題。這是否需要定期運行,或只有在對存儲過程進行更改時才運行? – Merritt 2009-08-13 17:59:07

+2

這是一個循環的基礎,因爲這些緩存的結果和計劃將逐漸積累。 – RoadWarrior 2009-09-15 14:52:27

1

爲什麼不把它一個DataReader,而不是DataAdapter的,它看起來像你有一個辛格運河結果集,如果你不打算要推動改變BAC k,並且不需要在.NET代碼中應用約束,則不應使用適配器。

編輯:

如果你需要的是一個DataTable你仍然可以通過一個DataReader拉從數據庫中的數據,然後在.NET代碼使用DataReader來填充的DataTable。這應該仍然比依靠數據集和DataAdapter更快

+0

我正在使用的代碼無法返回除此數據表以外的任何其他內容。 – 2008-10-30 16:16:46

0

我不知道「爲什麼」它本身就很慢 - 但正如馬庫斯指出的那樣 - 比較Mgmt Studio和填充數據集的結果是橙子。數據集包含很多開銷。我討厭他們,如果我能幫到他們,永遠不要使用他們。

您可能會遇到SQL堆棧舊版本的不匹配問題或某些此類問題(特別是您明顯陷於.NET 1.1中)該框架可能會嘗試執行數據庫「反射」的平等性來推斷模式等等等等

有一件事要考慮嘗試與你的不幸的約束是訪問與datareader數據庫,並在代碼中建立自己的數據集。你應該能夠通過谷歌輕鬆找到樣本。

+0

並請使用一些使用語句,因爲您的連接實現了IDisposable – 2009-01-29 18:42:35

4

這裏是我落得這樣做:

我執行下面的SQL語句來重建對數據庫中的所有表的索引:

EXEC <databasename>..sp_MSforeachtable @command1='DBCC DBREINDEX (''*'')', @replacechar='*' 
-- Replace <databasename> with the name of your database 

如果我想看看在SSMS相同的行爲,我跑這樣的PROC:

SET ARITHABORT OFF 
EXEC [dbo].[web_GetMyStuffFool] @UserID=1 
SET ARITHABORT ON 

另一種方式來繞過這是添加到您的代碼:

MyConnection.Execute "SET ARITHABORT ON" 
2

我遇到了同樣的問題,但是當我重建了SQL表的索引,它工作得很好,所以你可能要考慮在sql server端重建索引