Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL Datenbank / Timeout (https://www.delphipraxis.net/32608-sql-datenbank-timeout.html)

Jonny-Flash 26. Okt 2004 08:30


SQL Datenbank / Timeout
 
Hallo,
ich hoffe ihr könnt mir weiter helfen. Ich habe ein kleines Programm geschrieben, das Werte aus einer MSSQL-Datenbank liest, über diese einen Mittelwert bildet und diesen dann in einer anderen Tabelle abspeichert. Nun läuft das Programm anfangs recht gut, wird mit der Zeit aber immer langsamer und nach ca. 100 bis 150 Datensätzen bekomme ich die Fehlermeldung "Timeout abgelaufen". Wenn ich das Programm neu starte, ohne zu rebooten, kommt die Fehlermeldung schon nach ca. 15 Datensätzen.

Die Datenbanken :

Datenbank_A = Hier stehen alle Nummern der Datensätze (~500 Zeilen)
Datenbank_B = Hier gibt es zur Nummer den Zeitraum (~2.000.000 Zeilen)
Datenbank_C = Hier wird über den Zeitraum aus B der Mittelwert gebildet (~9.000.000)
Datenbank_D = Hier wird das Ergebnis gespeichert

Wie ihr sehen könnt sind die momentan bearbeiteten Datenbanken recht groß.

Und hier nun der Quelltext:
Delphi-Quellcode:
procedure TForm1.BtnLOSClick(Sender: TObject);
Var DateStart, DateStop, j : String;
    M_Fin2ManTemp, M_HeaterT1, M_HeaterT3, M_PLCCW1, M_PLCCW2, M_SupBlwr2, M_SupBlwr3 : double;
    count, i : Integer;
begin
  i := 0;
  j := IntToStr(Datenbank_A.RecordCount);
  Datenbank_A.First;
  while not Datenbank_A.Eof do
  begin
    Label1.Caption := 'Datensatz ' + IntToStr(i) + ' von ' + j;
    Form1.Repaint;
    with Datenbank_B do
    begin
      Close;
      CommandText := 'SELECT * FROM Datenbank_B' +
                     ' WHERE Nummer = ' + '''' + Datenbank_A.FieldByName('Nummer').AsString + '''' +
                     ' ORDER BY Date_Time';
      Open;
      First;
      DateStart := FieldByName('Date_Time').AsString;
      Last;
      DateStop := FieldByName('Date_Time').AsString;
    end;

    M_Fin2ManTemp := 0;
    M_HeaterT1 := 0;
    M_HeaterT3 := 0;
    M_PLCCW1 := 0;
    M_PLCCW2 := 0;
    M_SupBlwr2 := 0;
    M_SupBlwr3 := 0;

    with Datenbank_C do
    begin
      Close;
      CommandText := 'SELECT * FROM Datenbank_C ' +
                     ' WHERE Date_Time BETWEEN ' +
                     '''' + DateStart + '''' +
                     ' AND' +
                     '''' + DateStop + '''';
      Open;
      First;
      while not Datenbank_C.Eof do
      begin
        if FieldByName('Fin2ManTempFB').AsFloat <> NULL then
          M_Fin2ManTemp := M_Fin2ManTemp + FieldByName('Fin2ManTempFB').AsFloat
        else
          M_Fin2ManTemp := M_Fin2ManTemp + 0;

        if FieldByName('Heater T1 Gas Valve').AsFloat <> NULL then
          M_HeaterT1 := M_HeaterT1 + FieldByName('Heater T1 Gas Valve').AsFloat
        else
          M_HeaterT1 := M_HeaterT1 + 0;

        if FieldByName('Heater T3 Gas Valve').AsFloat <> NULL then
          M_HeaterT3 := M_HeaterT3 + FieldByName('Heater T3 Gas Valve').AsFloat
        else
          M_HeaterT3 := M_HeaterT3 + 0;

        if FieldByName('PLCCW1TarWG').AsFloat <> NULL then
          M_PLCCW1 := M_PLCCW1 + FieldByName('PLCCW1TarWG').AsFloat
        else
          M_PLCCW1 := M_PLCCW1 + 0;

        if FieldByName('PLCCW2TarWG').AsFloat <> NULL then
          M_PLCCW2 := M_PLCCW2 + FieldByName('PLCCW2TarWG').AsFloat
        else
          M_PLCCW2 := M_PLCCW2 + 0;

        if FieldByName('SupBlwr2\Speed').AsFloat <> NULL then
          M_SupBlwr2 := M_SupBlwr2 + FieldByName('SupBlwr2\Speed').AsFloat
        else
          M_SupBlwr2 := M_SupBlwr2 + 0;

        if FieldByName('SupBlwr3\Speed').AsFloat <> NULL then
          M_SupBlwr3 := M_SupBlwr3 + FieldByName('SupBlwr3\Speed').AsFloat
        else
          M_SupBlwr3 := M_SupBlwr3 + 0;
        Next;
      end;
    end;

    count := Datenbank_C.RecordCount;

    if count <> 0 then
    begin
      M_Fin2ManTemp := M_Fin2ManTemp / count;
      M_HeaterT1 := M_HeaterT1 / count;
      M_HeaterT3 := M_HeaterT3 / count;
      M_PLCCW1 := M_PLCCW1 / count;
      M_PLCCW2 := M_PLCCW2 / count;
      M_SupBlwr2 := M_SupBlwr2 / count;
      M_SupBlwr3 := M_SupBlwr3 / count;
    end;

    with Datenbank_D do
    begin
      Insert;
      Edit;

      FieldByName('Nummer').AsString := Datenbank_A.FieldByName('Nummer').AsString

      FieldByName('Fin2ManTempFB').AsFloat := M_Fin2ManTemp;
      FieldByName('Heater T1 Gas Valve').AsFloat := M_HeaterT1;
      FieldByName('Heater T3 Gas Valve').AsFloat := M_HeaterT3;
      FieldByName('PLCCW1TarWG').AsFloat := M_PLCCW1;
      FieldByName('PLCCW2TarWG').AsFloat := M_PLCCW2;
      FieldByName('SupBlwr2\Speed').AsFloat := M_SupBlwr2;
      FieldByName('SupBlwr3\Speed').AsFloat := M_SupBlwr3;

      Post;
      Next;
    end;
    Datenbank_A.Next;
    i := i + 1;
  end
end;

Leuselator 26. Okt 2004 18:21

Re: SQL Datenbank / Timeout
 
Das was Du da machst, lässt mir die Haare zu Berge steigen :cyclops:
Du kannst den ganzen Spass mit einem einzigen SQL-Statement erledigen (dafür sind ja "richtige" DB's da), ohne das alles in Delphi machen zu müssen.

Versuch es mal mit:
SQL-Code:
INSERT INTO Datenbank_D
         SELECT SUM(C.[Fin2ManTempFB]     )/COALESCE(COUNT(C.*),1)
              , SUM(C.[Heater T1 Gas Valve])/COALESCE(COUNT(C.*),1)
              , SUM(C.[Heater T3 Gas Valve])/COALESCE(COUNT(C.*),1)
              , SUM(C.[PLCCW1TarWG]       )/COALESCE(COUNT(C.*),1)
              , SUM(C.[PLCCW2TarWG]       )/COALESCE(COUNT(C.*),1)
              , SUM(C.[SupBlwr2\Speed]    )/COALESCE(COUNT(C.*),1)
              , SUM(C.[SupBlwr3\Speed]    )/COALESCE(COUNT(C.*),1)
           FROM Datenbank_A A
     INNER JOIN Datenbank_B B
             ON B.Nummer = A.Nummer
     INNER JOIN Datenbank_C C
             ON C.Date_Time BETWEEN min(B.Date_Time) AND max(B.Date_Time)
       GROUP BY A.NUMMER
Gruß

Jonny-Flash 27. Okt 2004 11:13

Re: SQL Datenbank / Timeout
 
Hi Leuselator,

danke für deine Hilfe. Sicher gibt es mehrere Wege, dieses Problem zu lösen. Allerdings hilft mir dein SQL-Statement "nur" für dieses Problem. Mein Programm soll noch neben der Mittelwertbildung auch noch eine Integralbildung beinhalten. Und nun habe ich trotzdem noch das Problem mit dem Time-Out Fehler beim abfragen größerer Datenbanken.
Nichts desto trotz habe ich deinen Code mal in den Query-Analyzer geworfen um zu schauen, wieviel schneller es damit ist und folgende Fehlermeldung erhalten.

Delphi-Quellcode:
Server: Nachr.-Nr. 170, Schweregrad 15, Status 1, Zeile 2
Zeile 2: Falsche Syntax in der Nähe von '*'.
Mit der Hilfe des Query Analyzers kann ich keine Fehler entdecken. Weder das COUNT noch das COALESCE erscheint mir fehlerhaft :?:


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:35 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