AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Parametrisiertes Insert plötzlich abnormal langsam
Thema durchsuchen
Ansicht
Themen-Optionen

Parametrisiertes Insert plötzlich abnormal langsam

Ein Thema von mariusbenz · begonnen am 9. Jan 2023 · letzter Beitrag vom 10. Jan 2023
Antwort Antwort
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
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.089 Beiträge
 
Delphi 12 Athens
 
#2

AW: Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 10:34
Ist das wirklich der reale Code im zweiten Abschnitt? Dort wird innerhalb der WHILE-Schleife ein SQL.Add gemacht ohne den vorigen Inhalt zu löschen.

Passiert zwar auch im ersten, aber da sieht man nicht, ob es mehrfach ausgeführt wird.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
mariusbenz

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

AW: Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 11:05
Hallo Uwe,

ich hatte hier etwas vereinfachten Quellcode eingefügt und es jetzt entsprechend angepasst. Es wird natürlich vorher immer geleert.
  Mit Zitat antworten Zitat
exon

Registriert seit: 12. Mär 2010
8 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 11:16
Hallo, unabhängig von dem Problem,

Wäre es evtl. sinnvoll, auf Batch-Operation umzustellen?

https://docs.devart.com/unidac/batchops.htm
  Mit Zitat antworten Zitat
Benutzerbild von dataspider
dataspider

Registriert seit: 9. Nov 2003
Ort: 04539 Groitzsch
1.350 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 11:29
Ist es auch richtig, dass du in der neuen Version Execute anstatt ExecSQL benutzt?
Möglicherweise gibt es da Unterschiede.

Die Zeile mit dem Prepare gehört IMO über das while unmittelbar nach dem Setzen des Statements.

Und Options.AutoPrepare der Query sollte False sein.

Frank
Frank Reim
  Mit Zitat antworten Zitat
mariusbenz

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

AW: Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 12:32
Hallo, unabhängig von dem Problem,

Wäre es evtl. sinnvoll, auf Batch-Operation umzustellen?

https://docs.devart.com/unidac/batchops.htm
Nach jedem Insert wird noch ein Update in einer anderen Tabelle gemacht, um im Fehlerfall genau den fehlerhaften Datensatz identifizieren zu können.

Wenn sowas "ganz plötzlich" passiert: gab es eventuell ein Update der DB-Server?

Habt ihr ansonsten mal probiert, das Statement umzuschreiben auf MERGE?
Es gab rund um den Zeitraum keine Updates auf betroffenen Systemen. Es war laut Log-Dateien von der 1 zur nächsten Minute plötzlich langsamer.

Ist es auch richtig, dass du in der neuen Version Execute anstatt ExecSQL benutzt?
Möglicherweise gibt es da Unterschiede.

Die Zeile mit dem Prepare gehört IMO über das while unmittelbar nach dem Setzen des Statements.

Und Options.AutoPrepare der Query sollte False sein.

Frank
AutoPrepare ist false. Prepare ist vermutlich an der Stelle, weil dann die Datentypen durch die Zuweisungen bekannt sind (wenn ich es davor setze, kommen irgendwelche CONVERT variant Exceptions).
Einen Unterschied zwischen Execute und ExecSQL wollte ich gerade mal testen, nur um festzustellen, dass wieder alles funktioniert??? Das lief seit dem 06.01. 05:01 bis zum Verfassen des Themas durchgehend langsam.

Ich beobachte das jetzt mal weiter.
  Mit Zitat antworten Zitat
Frickler

Registriert seit: 6. Mär 2007
Ort: Osnabrück
564 Beiträge
 
Delphi XE6 Enterprise
 
#7

AW: Parametrisiertes Insert plötzlich abnormal langsam

  Alt 9. Jan 2023, 11:25
Wenn sowas "ganz plötzlich" passiert: gab es eventuell ein Update der DB-Server?

Habt ihr ansonsten mal probiert, das Statement umzuschreiben auf MERGE?
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz