2013-12-10 2 views
-1

Мой запрос при запуске занимает около 7 секунд, чтобы сделать то, что предполагается. Но, поскольку он вставляет около 30 записей, я думаю, что это слишком медленно. Теперь я либо запускаю запрос, который не написано хорошо, или на самом деле это занимает много времени. Но это было бы странно. Основная база данных SQLite и запрос выглядит следующим образом:Delphi - запрос медленный

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», который является логическим (true/false).

Ответ, модифицированный (на основе 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

Вы должны назначить оператор SQL для UniQuery2 один раз вне цикла UniQuery1. Также определите параметры (ptInput и ftString/ftString), а затем, возможно, подготовьте запрос (dunno, если UniQuery имеет это). Затем в вашем цикле вам нужно только установить значения параметров. –

+0

Также, задавая вопросы с кодом, вы должны указывать определения переменных. Что это за тип UniQuery? Измените свой вопрос. –

+0

В качестве первого шага остановите использование цикла XXXByName в цикле, вместо этого используйте индексы. –

ответ

8

Не знаю Delphi, но предлагают некоторые улучшения:

  1. Вы не используете транзакции. У вас должно быть что-то вроде функции автоматической фиксации и команды COMMIT после всех вставок;

  2. Ваш SQL.Text:=... должен, вероятно, быть вне времени. Если это свойство задает компиляцию SQL-выражения, исключая его из-за этого, это предотвратит ненужные компиляции VDBE;

  3. Если ваше намерение является копированием строк из одной таблицы в другую (со статическим полем), вы можете делать с помощью одной команды SQL, как INSERT INTO MYTABLE SELECT :a1, FIELD2, FIEDL3, FIELD4 FROM source_table, установка ParamByName('a1').asString := AdvOfficeStatusBar1.Panels[0].Text

Это родовое DB улучшения использования, надеюсь, дает вам какое-то направление.

Предложение с использованием уникального 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; 
0

Если сам SQL INSERT медленно, я рекомендую, чтобы проверить его скорость выполнения в интерактивном режиме клиента первой. Или напишите простое тестовое приложение, которое выполняет один жестко запрограммированный INSERT и измеряет время его выполнения.

Также вы можете использовать отладчик, протоколирование или профилировщик, чтобы узнать, какая операция в вашем коде потребляет время - например, Uniquery1.Next или ExecSQL.

Смежные вопросы