Guten Morgen,
wir haben eine Datenschnittstelle, die Daten von lokalen
SQL-Express Servern auf einen globalen
SQL Server einliest. Diesen Einlesevorgang haben wir über die Jahre durch Indizes entsprechend optimiert, sodass wir 1000 Datensätze in ca. 1-3s einlesen können.
Vor ein paar Tagen hat sich dieser Prozess um den Faktor 1000 verlangsamt, so dass wir plötzlich bei 5s pro Datensatz lagen. Zugegebenermaßen hat die Tabelle 140.000.000 Datensätze und 4 Indizes, die ein Einfügen nicht schneller machen, aber ich hätte jetzt eher damit gerechnet, dass so etwas schleichend langsamer wird.
Hier mal der Quellcode dazu:
Delphi-Quellcode:
Que_G_MengenLogbuch_Insert.Close;
Que_G_MengenLogbuch_Insert.SQL.Clear;
Que_G_MengenLogbuch_Insert.SQL.Add(
'IF EXISTS(SELECT IDVonQuelle ' +
'FROM MDE_Mengen ' +
'WHERE ParamID = :ParamID ' +
'AND IDVonQuelle = :IDVonQuelle) ' +
'BEGIN ' +
'UPDATE MDE_Mengen ' +
'SET ParamID = :ParamID, ' +
'Delta = :Delta, ' +
'Anzahl = :Anzahl, ' +
'Zeit = :Zeit, ' +
'IDVonQuelle = :IDVonQuelle ' +
'WHERE ParamID = :ParamID ' +
'AND IDVonQuelle = :IDVonQuelle ' +
'END ' +
'ELSE ' +
'BEGIN ' +
'INSERT INTO MDE_Mengen (ParamID, Delta, Anzahl, Zeit, IDVonQuelle) ' +
'VALUES ( :ParamID, ' +
':Delta, ' +
':Anzahl, ' +
':Zeit, ' +
':IDVonQuelle) ' +
'END;');
while NOT (Que_L_Export.Eof) do
begin
Que_G_MengenLogbuch_Insert.Params.ParamByName('IDVonQuelle').AsInteger := Que_L_Export.FieldByName('ID').AsInteger;
Que_G_MengenLogbuch_Insert.Params.ParamByName('ParamID').AsInteger := Que_L_Export.FieldByName('ParamID').AsInteger;
Que_G_MengenLogbuch_Insert.Params.ParamByName('Delta').AsInteger := Que_L_Export.FieldByName('Delta').AsInteger;
Que_G_MengenLogbuch_Insert.Params.ParamByName('Anzahl').AsInteger := Que_L_Export.FieldByName('Anzahl').AsInteger;
Que_G_MengenLogbuch_Insert.Params.ParamByName('Zeit').AsDateTime := Que_L_Export.FieldByName('geaendert_am').AsDateTime;
if NOT(Que_G_MengenLogbuch_Insert.Prepared) then Que_G_MengenLogbuch_Insert.Prepare();
Que_G_MengenLogbuch_Insert.Execute();
Que_L_Export.Next;
end;
Das Que_G_MengenLogbuch_Insert.Execute() hier dauert ca. 5s.
Wenn ich das auf die unsichere und vermeintlich langsamere Methode umstelle, funktioniert alles wieder gewohnt schnell:
Delphi-Quellcode:
while NOT (Que_L_Export.Eof) do
begin
Que_G_MFA_MDE.Close;
Que_G_MFA_MDE.SQL.Clear;
Que_G_MFA_MDE.SQL.Add(
'IF EXISTS(SELECT IDVonQuelle ' +
'FROM MDE_Mengen ' +
'WHERE ParamID = ' + Que_L_Export.FieldByName('ParamID').AsString + ' ' +
'AND IDVonQuelle = ' + Que_L_Export.FieldByName('ID').AsString + ') ' +
'BEGIN ' +
'UPDATE MDE_Mengen ' +
'SET ParamID = ' + Que_L_Export.FieldByName('ParamID').AsString + ', ' +
'Delta = ' + IntToStr(Que_L_Export.FieldByName('Delta').AsInteger) + ', ' +
'Anzahl = ' + IntToStr(Que_L_Export.FieldByName('Anzahl').AsInteger) + ', ' +
'Zeit = ' + DateTimeToQuotedISO8601(Que_L_Export.FieldByName('geaendert_am').AsDateTime, true) + ', ' +
'IDVonQuelle = ' + Que_L_Export.FieldByName('ID').AsString + ' ' +
'WHERE ParamID = ' + Que_L_Export.FieldByName('ParamID').AsString + ' ' +
'AND IDVonQuelle = ' + Que_L_Export.FieldByName('ID').AsString + ' ' +
'END ' +
'ELSE ' +
'BEGIN ' +
'INSERT INTO MDE_Mengen (ParamID, Delta, Anzahl, Zeit, IDVonQuelle) ' +
'VALUES ( ' + Que_L_Export.FieldByName('ParamID').AsString + ', ' +
IntToStr(Que_L_Export.FieldByName('Delta').AsInteger) + ', ' +
IntToStr(Que_L_Export.FieldByName('Anzahl').AsInteger) + ', ' +
DateTimeToQuotedISO8601(Que_L_Export.FieldByName('geaendert_am').AsDateTime, true) + ', ' +
Que_L_Export.FieldByName('ID').AsString + ') ' +
'END;');
Que_G_MFA_MDE.ExecSQL;
Que_L_Export.Next;
end;
Kann sich jemand erklären, warum das parametrisierte plötzlich Statement so viel langsamer geworden ist?