2013-02-04 57 views
1

我有一個存儲過程正在執行INSERT語句,我們在執行時看到顯着的延遲。當從我們的C#.NET應用程序運行它以在一行中插入30條記錄時,總共需要大約4秒才能完成(只計算運行SqlCommand.ExecuteNonQuery()方法所需的時間)。但是,從SQL Server Management Studio中調用相同的確切存儲過程的次數只需要大約0.4秒。我無法弄清楚這兩種設置之間會有10倍速度的差別。存儲過程在.NET SqlCommand中比在SSMS中慢很多

我已經嘗試了所有與速度無明顯變化如下:

  1. 創建存儲過程「WITH RECOMPILE」
  2. 檢查所有正在內SSMS和C#配置的「設置」值的。唯一的區別是SET ARITHABORT,它在.NET應用程序中調用時處於SSMS狀態,處於OFF狀態。不過,將「SET ARITHABORT ON」添加到存儲過程的開始並沒有什麼區別。
  3. 從存儲過程中移除所有的默認值的參數

用於從.NET應用程序調用存儲過程中的代碼是:

using (SqlConnection newConn = new SqlConnection(connectionString)) 
{ 
    using (SqlCommand uCmd = new SqlCommand("sproc_name", newConn)) 
    { 
     uCmd.CommandType = CommandType.StoredProcedure; 
     uCmd.Connection.Open(); 

     //About 15 parameters added using: 
     uCmd.Parameters.AddWithValue("@ParamName", value); 
     ... 

     //One output parameter 
     SqlParameter paramOUT = new SqlParameter("@OutPutKey", SqlDbType.UniqueIdentifier); 
     paramOUT.Direction = ParameterDirection.Output; 
     uCmd.Parameters.Add(paramOUT); 

     uCmd.ExecuteNonQuery(); 
     uCmd.Connection.Close(); 
    } 
} 

存儲過程本身只是一組命令的列表(SET ANSI_NULLS ON,SET QUOTED_IDENTIFIER ON,SET ARITHABORT ON),非默認參數列表以及輸出變量的設置,該變量將成爲將作爲主鍵插入到表中的新唯一標識符,然後是INSERT語句本身。

的應用是建立在.NET 4和SQL服務器是MS SQL Server 2005中

這裏是插入存儲過程中它調用的一個例子:

alter procedure InsertStuff 
@Field1 uniqueidentifier, 
@Field2 datetime, 
... 
@CreateDate datetime, 
@PrimaryKEY uniqueidentifier OUTPUT 
AS 

declare @newCreateDate datetime 
set @newCreateDate=getDate() 

set @PrimaryKEY = NEWID() 

INSERT INTO [dbo].[Table] 
(
    Field1, 
    Field2, 
    ... 
    CreateDate, 
    PrimaryKEY 
) 
VALUES 
(
    @Field1, 
    @Field2, 
    ... 
    @newCreateDate, 
    @PrimaryKEY 
) 
+6

沒有看到存儲過程很難回答, 聽起來,你在調用這個方法30次,但從你的代碼打開和關閉,處理連接30次。保持連接打開,然後調用存儲過程30次。 – Peter

+1

也只是設置一次命令,只是爲每個調用添加參數值 –

+0

這個問題可能會幫助http://stackoverflow.com/questions/801909 – devio

回答

2

有可能的問題是,每個執行命令調用都會執行一次網絡跳轉,其中ssms將一次批量發送全部30個命令到服務器。我相信默認情況下,SSMS會將所有30條語句作爲一個批次發送,但是如果您更改了可能影響事件的其他設置。

此外,請確保您每次都不打開和關閉連接。儘管連接池可能不會成爲問題,但我不會放棄。

+1

連接池不會使其成爲非問題,因爲重新使用池連接仍會導致額外的往返行爲,因爲在同一連接上爲連接重新設置新的「會話」。 「SSMS將會批量發送所有30個命令」,真正解決SSMS測試的問題(在一個批次中循環,或者30個獨立批次) - 你是對的,爲了比較蘋果和蘋果, SSMS測試應實施爲30批次,用「GO」批分離器分隔。 – Tao

+0

@Tao是的,有一些重置可能會完成(我實際上已經聽說池的連接有意外的設置,如不同的超時,所以我不知道實際重置了多少)。建立連接通常比發送命令更昂貴,但我明白你的觀點。這實際上取決於「重置」完成了多少。我已經更新了我的答案,希望能夠更清楚地表明我正在假設SSMS的默認設置。 – Andy

+0

所以事實證明,我的測試環境已經搞砸了,實際上,從.NET和SSMS調用此插入存儲過程的速度大致相同。但是,我正在考慮共享單個SqlConnection和單個SqlCommand(在至少調用相同存儲過程的情況下)。這給了我大約25%的節省速度。不過,我仍然認爲它應該能夠比這更快地完成這些插入操作。我添加了一個插入存儲過程的示例。你看到有其他需要改進的空間嗎? – Rett

相關問題