[請教]多筆資料快速寫入資料庫 |
|
peipei36
一般會員 發表:8 回覆:51 積分:16 註冊:2002-03-13 發送簡訊給我 |
|
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
引言: 請教各位先進們... 若我有一百筆甚至更多的資料要寫入資料庫~ 例如,我有一個CheckListBox讓user可以核選資料, 我要將user核選的資料(可能對應到資料庫table的客戶編號)寫回資料庫, 可以不要「一筆一筆」寫入資料庫嗎?因為這樣好像速度會很慢... 不曉得應以什麼方式處理這樣的問題... 感謝大家幫忙!! 發表人 - peipei36 於 2002/03/13 23:04:20您可以將TQuery的Cache Update打開, 例用Start transaction .... update sql applyupdate end transaction 如此雖然程式內容為一筆一筆處理,但對資料庫來講是一整筆交易, 如此效能會高! 不過筆數太多時,不宜全部塞入一個交易中, 因為資料庫中的覆原區塊(Rollback)有限的,會弄暴的,建議一個交易中不要超過1000筆SQL指令 若還有問題歡迎post程式大家來嘗試如何寫出最有效率的轉入程式 ~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
peipei36
一般會員 發表:8 回覆:51 積分:16 註冊:2002-03-13 發送簡訊給我 |
|
scottliou
版主 發表:16 回覆:56 積分:47 註冊:2002-03-14 發送簡訊給我 |
使用transaction對於無DBA的資料庫使用者而言常常會因為本身資料庫
RollBack Block開放空間的問題而導致失敗,所以如果可允許些許資料
遺漏時可使用下列方法 table.cachedUpdates=>true; with table do bgein
try
i:=1;
try
AppendRecord([..,..,..,....]);
except
end;
if i =1000 then //每1000筆commit一次
begin
CommitUpdates;
i:=0;
end;
inc(i);
finally
CommitUpdates;
end;
end;
這樣速度應該可以吧!!
請自已試試看!!..... ~~~~~~~~~~~~~~~~
有夢想最美...... [優良回覆]
------
~~~~~~~~~~~~~~~~ 有夢想最美...... |
peipei36
一般會員 發表:8 回覆:51 積分:16 註冊:2002-03-13 發送簡訊給我 |
|
Diviner
初階會員 發表:36 回覆:112 積分:34 註冊:2002-03-13 發送簡訊給我 |
引言: 感謝站大幫忙...努力試試! 另外,交易是否意謂著必須全部成功or全部失敗?! 假若原來的問題,記錄的是大量筆數的資料,但可以允許些許資料遺漏, 例如,可能記錄的只是坐標or顏色的變化... (也就是1000筆的資料允許幾筆寫回資料庫失敗..) 同樣交由交易處理嗎?!或者有其他的方式處理?! ps.不好意思,觀念還不大清楚,並無具體程式碼... 文字表達不清,請海涵^^~寫個迴路, 一筆一筆的寫回Database, 有何困難? 成功的就從你所說的 CheckListBox 中除去, Error 的保留, 就這樣。 發表人 - Diviner 於 2002/03/14 10:49:02
------
-- 小卜子 |
peipei36
一般會員 發表:8 回覆:51 積分:16 註冊:2002-03-13 發送簡訊給我 |
不好意思..最近有點事耽擱了...到現在才試...
我試了站大& scottliou 您們的方法...
但是,不管在本機的Access或網路(區網)的SQL Server..
速度竟然都是 直接Post > Transaction > CacheUpdates...
(本機access 2000;OS=98 區網sql server 2000;OS=2000pro)
// 測試結果(資料300筆): // 1. 本機 access => Transaction = 1.26 s // CacheUpdate = 3.74 s // Post = 0.55 s // 2. 區網 SQL Server 200x => // Transaction = 0.88 s // CacheUpdate = 3.02 s // Post = 0.55 s不知是不是我的程式碼有問題?!還是另有什麼該注意的?! 能否請大家再幫我看看!!感謝您們哦~^^ 程式碼不大,但感覺很佔篇幅,我另放在[url="http://210.240.6.173/~robert/download/testCacheUpd.zip"]這裡(zip,4.48KB)[/url]...謝謝大家的幫忙!! ps. 程式碼中,CacheUpdates依照scottliou上次提的方式;Transaction我還不 熟...不知這樣寫對不對(湊得很硬^^~)!! 另外,感謝Diviner您的幫忙...我本來是直接用Post...但覺得速度很慢.. 因此想看是不是有比較有效率的方式.... ★另外,如果用 CheckListBox1.Items.SaveToFile('xxx') 的方式, 再透過database 將文字檔匯入不知會不會快些?!大家能提供點意見嗎?!thx~ (只是想到...我還不清楚如何轉檔..) ↓↓感謝站大~我完全不會介意的(原僅是怕佔版面^^~).. ↓↓ 另外,CacheUpdate與Transaction我真的是搞不大清楚, ↓↓ 謝謝您的說明,我這幾天要將Help好好KK了~thx~ 發表人 - peipei36 於 2002/03/19 21:56:26 |
領航天使
站長 發表:12216 回覆:4186 積分:4084 註冊:2001-07-25 發送簡訊給我 |
引言: // 測試結果(資料300筆): // 1. 本機 access => Transaction = 1.26 s // CacheUpdate = 3.74 s // Post = 0.55 s // 2. 區網 SQL Server 200x => // Transaction = 0.88 s // CacheUpdate = 3.02 s // Post = 0.55 s 不知是不是我的程式碼有問題?!還是另有什麼該注意的?!很有趣的話題! 1.Access非Database Server的資料庫,所以對Transaction處理較差,先不論 2.SQL Server 2000 的post居然比Transaction快,我用您的程式測也是如此 但我發現您在CacheUpdate的按鈕程式中將table1.cacheupdate=true, 之後再去測post,結果是因為 post未將結果寫入,只是放在Cache而已,速度當然快,不信的話您先跑post再跑Transaction就知道了 3.SQL Server 2000 的CacheUpdate居然比Post慢,我測也是如此, 您在CacheUpdate的程式中用CommitUpdates,而不是用Cacheupdate. 您可能把Transaction與CacheUpdate混為一談了: 1.Transaction為Database Server內部提供的整筆交易存入資料庫用, 用來確保資料的一致性,例如在:Master/Detail的出貨記錄上, 出貨表頭(Master)的Table必須與出貨內容(Detail)的Table同進退, 若其中有一個Table有Insert上的問題時,必需兩個Table一起Rollback, 都沒問題才一起Commit,不可有頭無尾或有尾無頭! 2.Cacheupdate為Delphi的BDE內部做的Buffer(這個Buffer就是Paradox), 大部份用來在User即時輸入資料的各欄位時增進效能用,通常在存檔的功能 上將之前所有的修改一起ApplyUpdate,因ApplyUpdate為BDE自己處理SQL指令, 所以會有很多繞道的SQL指令做法! 不知這樣說明會不會很難懂? 我將您的原始程式列出,請網友們"大家來找碴",看看還有那些地方是錯誤的寫法! (請peipei36網友不要介意,站長是想大家一起來成長) unit Unit2; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DBTables, StdCtrls, CheckLst; type TForm1 = class(TForm) Button1: TButton; Table1: TTable; CheckListBox1: TCheckListBox; Button3: TButton; Button2: TButton; Query1: TQuery; Database1: TDatabase; Label1: TLabel; Label2: TLabel; Label3: TLabel; procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure FormActivate(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var i,nCnt,ntmpPos:integer; ctmpStr:string; t1:TDateTime; begin table1.Close; table1.EmptyTable; // delete all records table1.Open; table1.CachedUpdates := true; t1 := now; with table1 do begin for i:=1 to CheckListBox1.Items.Count do begin try nCnt:=1; try if CheckListBox1.Checked[i] then begin ctmpStr := CheckListBox1.Items[i]; ntmpPos := AnsiPos(' ',ctmpStr); AppendRecord([Copy(ctmpStr,1,ntmpPos-1),Copy(ctmpStr,ntmpPos 1,Length(ctmpStr))]); end; except end; if nCnt =1000 then //¨C1000µ§commit¤@¦¸ begin CommitUpdates; nCnt:=0; end; Inc(nCnt); finally CommitUpdates; end; end; end; Label2.Caption := floatToStr((now-t1)*86400); end; procedure TForm1.Button3Click(Sender: TObject); var i,ntmpPos:integer; ctmpStr:string; t1:TDateTime; begin table1.Close; table1.EmptyTable; table1.open; t1 := now; for i:=0 to CheckListBox1.Items.Count-1 do begin if CheckListBox1.Checked[i] then begin ctmpStr := CheckListBox1.Items[i]; ntmpPos := AnsiPos(' ',ctmpStr); table1.Append; table1.Fields[0].AsString := Copy(ctmpStr,1,ntmpPos-1); table1.Fields[1].AsString := Copy(ctmpStr,ntmpPos 1,Length(ctmpStr)); table1.Post; end; end; Label3.Caption := floatToStr((now-t1)*86400); table1.close; end; procedure TForm1.FormActivate(Sender: TObject); var i:integer; begin for i:=0 to checklistbox1.Items.Count-1 do checkListBox1.Checked[i] := true; end; procedure TForm1.Button2Click(Sender: TObject); var i,nCnt,ntmpPos:integer; ctmpStr,ctmpSql:string; t1:TDateTime; begin table1.Close; table1.EmptyTable; // delete all records table1.Open; Database1.Open; Query1.CachedUpdates := true; t1 := now; try if Database1.InTransaction then Database1.Rollback; Database1.StartTransaction; nCnt:=1; for i:=0 to CheckListBox1.Items.Count-1 do begin if CheckListBox1.Checked[i] then begin ctmpStr := CheckListBox1.Items[i]; ntmpPos := AnsiPos(' ',ctmpStr); ctmpSql := 'INSERT INTO ZZZ1 VALUES(''' // for SQL server -> into dbo.ZZZ1 Copy(ctmpStr,1,ntmpPos-1) ''',''' Copy(ctmpStr,ntmpPos 1,Length(ctmpStr)) ''')'; Database1.Execute(ctmpSql); end; if nCnt =1000 then //¨C1000µ§commit¤@¦¸ begin try Database1.Commit; nCnt:=0; except Database1.Rollback; end; end; Inc(nCnt); end; finally try Database1.Commit; except Database1.Rollback; end; end; Label1.caption := floatToStr((now-t1)*86400); end; end. [/code] ~~~Delphi K.Top討論區站長~~~
------
~~~Delphi K.Top討論區站長~~~ |
skylin
一般會員 發表:0 回覆:2 積分:0 註冊:2002-04-15 發送簡訊給我 |
|
terrychen
尊榮會員 發表:90 回覆:794 積分:501 註冊:2003-05-01 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |