【问题标题】:Delphi - Query running slowDelphi - 查询运行缓慢
【发布时间】:2013-12-10 07:12:08
【问题描述】:

我的查询,运行时大约需要 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”之外,所有字段都是文本。

修改后的答案(基于 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;

【问题讨论】:

  • 您应该在 UniQuery1 循环之外为 UniQuery2 分配 SQL 语句。还要定义参数(ptInput 和 ftString/ftString),然后可能准备查询(不知道 UniQuery 是否有)。然后在你的循环中你只需要设置参数值。
  • 另外,当用代码提问时,变量定义需要在场。这种 UniQuery 是什么动物?编辑您的问题。
  • 第一步,停止在循环中使用XXXByName,改用索引。
  • 我需要查看所有 UNIQuery1 记录。我不确定我是否在关注你。你能给我一些关于你认为应该如何的代码吗?
  • Android SQLite database: slow insertion 的可能重复项;这是FAQ

标签: sql sqlite delphi delphi-xe4 unidac


【解决方案1】:

不了解 Delphi,但会提出一些改进建议:

  1. 您没有使用事务。在所有插入之后,您应该有类似 auto-commit disabled 和 COMMIT 命令之类的东西;

  2. 您的SQL.Text:=... 可能已经过时了。如果此属性集编译 SQL 语句,将其置于 while 之外将防止不必要的 VDBE 编译;

  3. 如果您的意图是将行从一个表复制到另一个表(使用静态字段),您可以使用像 INSERT INTO MYTABLE SELECT :a1, FIELD2, FIEDL3, FIELD4 FROM source_table 这样的单个 SQL 命令,设置 ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text

这是通用的数据库使用改进,希望能给你一些方向。

使用唯一 SQL 的建议:

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;

【讨论】:

    【解决方案2】:

    如果 SQL INSERT 本身很慢,我建议先在交互式客户端中测试它的执行速度。或者编写一个简单的测试应用程序,执行一个硬编码的 INSERT 并测量其执行时间。

    您还可以使用调试器、日志记录或分析器来找出代码中耗时的操作 - 例如,它可能是 Uniquery1.NextExecSQL

    【讨论】:

      猜你喜欢
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-24
      • 2019-04-15
      • 2011-04-27
      • 1970-01-01
      相关资源
      最近更新 更多