2013-12-10 80 views
-1

我的查詢,運行時需要大約7秒來做什麼應該。但是,因爲它插入了大約30條記錄,我認爲它太慢了。現在,無論我運行的查詢是寫得不好,或者確實需要這麼多時間。但那會很奇怪。基礎數據庫是SQLite和查詢看起來是這樣的:德爾福 - 查詢運行緩慢

procedure TForm1.cxButton1Click(Sender: TObject); 
begin 
with UNIquery2 do begin 
    Close; 
    SQL.Clear; 
UNIQuery1.First; 
while Uniquery1.EOF = false do begin 
SQL.Text:= 'INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) VALUES (:a1,:a2,:a3,:a4)'; 
     ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text; 
     ParamByName('a2').asString := UniTable1.FieldByName('FIELD2').asString; 
     ParamByName('a3').asString := Uniquery1.FieldByName(',FIELD3').asString; 
     ParamByName('a4').Value := Uniquery1.FieldByName('FIELD4').Value;//boolean field true/false 
     Uniquery1.Next; 
     ExecSQL; 
end; 
end; 
end; 

所以有人可以告訴我,如果這是確定還是我失去了一些東西? 所有字段都是文本,除了'a4'是布爾值(真/假)。

答案,修改(基於suuggestion從LS_dev):

procedure TForm1.cxButton1Click(Sender: TObject); 
begin 
    with UNIquery2 do begin 
     Close; 
     SQL.Clear; 
     SQL.Add('INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) VALUES (:a1,:a2,:a3,:a4)'); 
     SQL.Prepare; 
     UniTransaction.AddConnection(UniConnection2); 
     UniTransaction.StartTransaction; 
try 
     UNIQuery1.First; 
     while Uniquery1.EOF = false do begin 
      Params[0].asString := AdvOfficeStatusBar1.Panels[0].Text; 
      Params[1].asString := UniTable1.FieldByName('FIELD2').asString; 
      Params[2].asString := Uniquery1.FieldByName(',FIELD3').asString; 
      Params[3].Value := Uniquery1.FieldByName('FIELD4').Value;//boolean field true/false 
      Uniquery1.Next; 
      ExecSQL; 
     end; 
     UniTransaction.Commit; 
finally 
    if UNIquery2.Connection.InTransaction then 
    UNIquery2.Connection.Rollback; 
    end; 
    end; 
    end; 
+1

您應該UniQuery1循環外指定SQL語句UniQuery2一次。也可以定義參數(ptInput和ftString/ftString),然後可以準備查詢(如果UniQuery有,則不知道)。然後在你的循環中,你只需要設置參數值。 –

+0

此外,當用代碼提問時,您需要提供變量定義。什麼是UniQuery這種動物?編輯你的問題。 –

+0

作爲第一步,停止在循環中使用'XXXByName',而不是使用索引。 –

回答

8

不知道德爾福,但會提出一些改進:

  1. 您沒有使用事務。在所有插入之後,您應該有類似禁用自動提交和COMMIT命令的內容;

  2. 您的SQL.Text:=...應該可能不在時。如果此屬性集合編譯SQL語句,則將其從while刪除,以防止不必要的VDBE編譯;

  3. 如果你的意圖是複製從一個表到另一個行(與靜態字段),你可以使用一個SQL命令像INSERT INTO MYTABLE SELECT :a1, FIELD2, FIEDL3, FIELD4 FROM source_table做,設置ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text

這是通用的數據庫使用的改善,希望給你一些方向。

建議採用獨有的SQL:使用改進的DB處理

procedure TForm1.cxButton1Click(Sender: TObject); 
begin 
    with UNIquery2 do 
    begin 
     SQL.Clear; 
     SQL.Add('INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) SELECT ?,FIELD2,FIELD3,FIELD4 FROM UNIquery1_source_table'); 
     Params[0].asString := AdvOfficeStatusBar1.Panels[0].Text; 
     ExecSQL; 
    end; 
end; 

建議:

procedure TForm1.cxButton1Click(Sender: TObject); 
begin 
    with UNIquery2 do 
    begin 
     Close; 
     SQL.Clear; 
     SQL.Add('INSERT INTO MYTABLE (FIELD1,FIELD2,FIELD3,FIELD4) VALUES (:a1,:a2,:a3,:a4)'); 
     SQL.Prepare; 
     UniTransaction.AddConnection(UniConnection2); 
     UniTransaction.StartTransaction; 
     UNIQuery1.First; 
     while Uniquery1.EOF = false do 
     begin 
      Params[0].asString := AdvOfficeStatusBar1.Panels[0].Text; 
      Params[1].asString := UniTable1.FieldByName('FIELD2').asString; 
      Params[2].asString := Uniquery1.FieldByName(',FIELD3').asString; 
      Params[3].Value := Uniquery1.FieldByName('FIELD4').Value;//boolean field true/false 
      Uniquery1.Next; 
      ExecSQL; 
     end; 
     UniTransaction.Commit; 
    end; 
end; 
0

如果SQL INSERT本身很慢,我建議首先測試其執行速度在交互式客戶端。或者編寫一個簡單的測試應用程序,執行一個硬編碼的INSERT並測量其執行時間。

也可以使用調試器,日誌記錄或分析器來查找代碼中消耗時間的操作 - 例如,它可以是Uniquery1.NextExecSQL