2012-09-13 63 views
6

我需要改善數據加載的性能。目前algorythm使得從表中全選擇:如何提高數據插入/更新性能?

select Field1, Field2,...,FieldN from Table1 order by FieldM 

新的數據從一個文本文件中讀取(比如說,每行數據錶行文本文件)。 表中有一個主鍵,包含兩個字段。對於文本文件的每一行,它通過這兩個字段(即主鍵)定位必要的行。

query.Locate('Field1;Field2',VarArrayOf([Value1,Value2]),[]); 

如果Locate回報True,它編輯該行,否則它附加一個新的。

因此,只要表格包含大約200000行,每個操作都需要一定的時間......因此它每秒鐘可以更新大約5-6行。

我應該考慮什麼來改善它?

可能替換通過這個偉大的選擇與單獨的查詢定位?

回答

10

請勿使用Locate()。如果你使用locate(),那麼Delphi在客戶端搜索行只是從你的查詢中掃描行集,它需要很多時間。

如果您有權訪問MSSQL來創建存儲過程,那麼創建以下過程,並在沒有任何條件的情況下(在Delphi中使用TAdoStoredProc.ExecProc)從TEXT文件中的每一行運行它。所以在這種情況下,你不需要先選擇和定位程序。如果找到Filed1和Field2,它會更新記錄,如果不存在則插入。

CREATE PROCEDURE dbo.update_table1 
@Field1 int, --key1 
@Field2 int, --key2 
@Field3 int, -- data fileds 
@Field4 int 

AS 

SET NOCOUNT ON 
update table1 set [email protected],[email protected] 
     where [email protected] and [email protected]; 
IF(@@Rowcount=0) 
BEGIN 
    insert into table1(Field1,Field2,Field3,Field4) 
       values (@Field1,@Field2,@Field3,@Field4); 
END 
GO 

下面是Delphi代碼調用與ADO這個存儲過程:

...... 
var 
    ADOStoredP: TADOStoredProc; 

    ...... 
begin 

........ 
    ADOStoredP:=TADOStoredProc.Create(nil); 
    try 
     ADOStoredP.Connection:=DataMod.SQL_ADOConnection; //Your ADO Connection instance here 
     ADOStoredP.ProcedureName:='Update_table1'; 
     ADOStoredP.Parameters.CreateParameter('@Field1', ftInteger, pdInput, 0, 0); 
     ADOStoredP.Parameters.CreateParameter('@Field2', ftInteger, pdInput, 0, 0); 
     ADOStoredP.Parameters.CreateParameter('@Field3', ftInteger, pdInput, 0, 0); 
     ADOStoredP.Parameters.CreateParameter('@Field4', ftInteger, pdInput, 0, 0); 

     While() -- Your text file loop here 
     begin 

     ADOStoredP.Parameters.ParamByName('@Field1').Value:=Field1 value from text file here; 
     ADOStoredP.Parameters.ParamByName('@Field2').Value:=Field2 value from text file here; 
     ADOStoredP.Parameters.ParamByName('@Field3').Value:=Field3 value from text file here; 
     ADOStoredP.Parameters.ParamByName('@Field4').Value:=Field4 value from text file here; 

     ADOStoredP.ExecProc; 

     end 

    finally 
     if Assigned(ADOStoredP) then 
     begin 
     ADOStoredP.Free; 
     end; 
    end; 

........ 
end; 
+3

該解決方案將加載時間從4小時減少到4分鐘以內。我非常感謝你的幫助!謝謝! – horgh

5
  1. 如果可能,那麼您應該將文本文件發送到運行SQL Server的服務器。然後使用OPENROWSET(BULK)打開文本文件(請參閱「E.使用帶格式文件的OPENROWSET BULK提供程序從文本文件中檢索行」)。
  2. 如果無法將文本文件發送到服務器,則創建一個臨時或持久數據庫表並使用INSERT將所有文本文件行插入表中。
  3. 如果您使用的是SQL Server 2008,那麼您應該使用MERGE運算符。如果更舊的SQL Server版本,則可以使用兩個SQL命令:UPDATE和INSERT。並且作爲數據源使用(1)OPENROWSET或(2)數據庫表。
+0

雖然這是很容易通過VALEX我的情況適用答案,謝謝你的幫助。目標SQL Server甚至是2000年。一個很老的。由於valex提供的想法,重新制作整個算法以將文件加載到某個臨時表(等等......)與我所取得的成果(以及我花費了多少時間)相比,不值得任何性能增益(如果有的話) 。不管怎樣,謝謝! – horgh