Delphi - Query running slow

2.6k views Asked by At

My query,when run takes about 7 seconds to do what is supposed to.But,since its inserting about 30 records,I think it is too slow.Now,either I am running the query that is not written well or it does actually takes this much time. But that would be strange. The underlying database is SQLite and the query looks like this :

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;

So can someone tell me if this is OK or am I missing something ? All fields are text except the 'a4' which is boolean (true/false).

The answer,modified (based on suuggestion from 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;
2

There are 2 answers

0
LS_ᴅᴇᴠ On BEST ANSWER

Don't know Delphi, but will suggest some improvements:

  1. You are not using a transaction. You should have something like something like auto-commit disabled and COMMIT command after all insertions;

  2. Your SQL.Text:=... should probably be out of while. If this property set compiles SQL statement, putting it out of while will prevent unnecessary VDBE compilations;

  3. If your intent is copying rows from one table to another (with a static field), you may doing using a single SQL command like INSERT INTO MYTABLE SELECT :a1, FIELD2, FIEDL3, FIELD4 FROM source_table, setting ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text

This is generic DB usage improvement, hope gives you some direction.

Suggestion using unique 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;

Suggestion using improved DB handling:

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
mjn On

If the SQL INSERT itself is slow, I recommend to test its execution speed in an interactive client first. Or write a simple test application which performs one hard-coded INSERT and measures its execution time.

Also you can use the debugger, logging or a profiler to find out the operation in your code which consumes time - it could be the Uniquery1.Next or the ExecSQL for example.