2013-12-10 36 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