Einzelnen Beitrag anzeigen

mariusbenz

Registriert seit: 6. Mär 2015
38 Beiträge
 
Delphi 10.3 Rio
 
#1

Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 10:21
Datenbank: MS SQL • Version: 14.0.3356.20 • Zugriff über: UniDAC
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?

Geändert von mariusbenz ( 9. Jan 2023 um 11:03 Uhr)
  Mit Zitat antworten Zitat