Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Große Datenmengen richtig verarbeiten bzw. Out of Memory (https://www.delphipraxis.net/197012-grosse-datenmengen-richtig-verarbeiten-bzw-out-memory.html)

p80286 12. Jul 2018 23:04

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1407044)
Identische Komponenten, aber unterschiedliche Datenbanken können, wenn auch seeeeeehr selten, zu solchen Problemen führen.

Wo Du es beschreibst...gleiche DB, gleiche Komponente, zwei unterschiedliche ADO-Treiber

Gruß
K-H

MichaelT 13. Jul 2018 08:48

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Diese Unart alles zu holen kam mit Access auf resp. hat Access den Trend verstärkt * zu nehmen anstatt konkrete Datenmengen zu definieren.

In weiter Folge wird kein Wert mehr darauf gelegt ob ein Join Kriterium ein Integer ist usw...

Peu a peu wird's langsam.

Access ware eine der ersten DBs die den Spaltentyp aufgrund der Analyse von ein paar Datensätzen hat geraten.



Zitat:

Zitat von hoika (Beitrag 1406828)

select id,*
Brauchst Du wirklich alle Felder der Tabelle?

Das könnte schon das [/DELPHI]


MichaelT 13. Jul 2018 09:03

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
In Ergänzung: Es bietet sich in solchen Fällen über Arrays im Mittel ganz performant auf Datenmengen zugreift.

Wir haben die Arraysize bis zu einem Limit bei jedem Fetch verdoppelt bis das Limit hinter dem keine Geschwindigkeitszugewinn mehr zu holen war.

Zumindest auf Oracle und SQL Server hat die 'Strategie' sehr gute Ergebnisse geliefert egal wieviele Sätze in den Tabellen gespeichert waren.

Zitat:

Zitat von jaenicke (Beitrag 1406847)
Ich habe zu dem Zweck ein Histogramm zur Werteverteilung vom MS SQL Server gezogen und dann immer eine möglichst gleich große Anzahl von Zeilen abgeholt.


Delphi.Narium 13. Jul 2018 16:26

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Zitat:

Zitat von p80286 (Beitrag 1407097)
Zitat:

Zitat von Delphi.Narium (Beitrag 1407044)
Identische Komponenten, aber unterschiedliche Datenbanken können, wenn auch seeeeeehr selten, zu solchen Problemen führen.

Wo Du es beschreibst...gleiche DB, gleiche Komponente, zwei unterschiedliche ADO-Treiber

Gruß
K-H

Exakt.

Wenn man mal bei DB-Zugriffen "ungewöhnliches" Verhalten seitens seines Delphiprogrammes beobachtet:

Es kann sehr hilfreich sein, sich die Datenbankverbindung und die Treiber anzuschauen / anzupassen, statt im Programmquelltext mehr oder weniger verzweifelt nach Workarounds um festgestellte Probleme zu suchen.

Früher (zu BDE-Zeiten) konnte es durchaus hilfreich sein, beim Zugriff auf Oracle auch deren Treiber zu nehmen und nicht den von Microsoft, der (damals?) auf den Systemen schon vorhanden war.

Keine Ahnung, wie sich das bis heute so entwickelt hat, aber die Fehlermöglichkeiten zwischen eigenem Programm und Datenbank sollte man nie ausklammern.

@MichaelT

select * from ist eine Unsitte, die verboten gehört. Es wird nur das selektiert, was man auch benötigt -> kleinstmögliche Ergebnismenge, sowohl in Bezug auf die ausgewählten Spalten als auch auf die ausgewählten Zeilen.

Alles zu holen und dann im Programm nur das benötigte zu verarbeiten ist einfach nur schlecht.

jobo 13. Jul 2018 21:45

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1407230)
select * from ist eine Unsitte,..
..
Alles zu holen und dann im Programm nur das benötigte zu verarbeiten ist einfach nur schlecht.

[/quote]

Unsitte, nicht unbedingt
Alles zu holen ist tatsächlich schlecht.

Wenn hinter dem from eine definierte Datenquelle hängt (view), die Spalten und Zeilen wie gewünscht eingrenzt, finde ich es nicht problematisch.
Spaß macht es, wenn man die Datenquelle ändert und "Select *" in der Anwendung einfach die zusätzlichen (oder weniger) Daten liefert.
Dazu gehört allerdings eine eigene Feldverwaltung.

Delphi.Narium 14. Jul 2018 14:27

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Zitat:

Zitat von jobo (Beitrag 1407248)
Wenn hinter dem from eine definierte Datenquelle hängt (view), die Spalten und Zeilen wie gewünscht eingrenzt, finde ich es nicht problematisch.
Spaß macht es, wenn man die Datenquelle ändert und "Select *" in der Anwendung einfach die zusätzlichen (oder weniger) Daten liefert.
Dazu gehört allerdings eine eigene Feldverwaltung.

Naja, prinzipiell hast Du ja recht, aber, wenn einer eine identische Tabelle, 'ne identische View erstellt, aber "nur" die Spalten im Create in 'ner anderen Reihenfolge angibt, kannst Du bereits die ersten Probleme bekommen.
Delphi-Quellcode:
i := qry.fields[1].AsInteger
könnte schon scheitern, weil die hier ursprunglich erwartete Spalte eventuell eine andere Position bekommen hat und wir hier den Inhalt einer Zeichenkette bekommen und nicht den in Spalte 1 erwarteten Integer.

Und wenn man statt * die benötigten Spalten angibt, schreibt man zwar mehr, aber wenn davon eine Spalte "verlustig" gehen sollte, knallt das SQL, die Query beim Open, und nicht erst ein eventuell viel später erfolgender Zugriff auf die "verschwundene" Spalte.

Mag es halt, wenn Fehler möglichst nah an der Fehlerursache auftreten und wenn eine mögliche Fehlerursache im SQL liegen kann, dann möchte ich, dass das SQL mir "um die Ohren fliegt" und nicht erst die Verarbeitung der erhaltenen, aber nicht so erwarteten, Ergebnismenge.

Monday 4. Aug 2018 20:19

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Erstmal vielen Dank für eure Antworten.

Ich habe gerade gesehen, dass mir bei dem Beitrag ein Fehler unterlaufen ist. Ausgerechnet die wichtigste Zeile fehlt:
temp := temp+100;

Dieser kommt am Schluss. Ich habe unten nochmal den überarbeiteten code angefügt.


"Form1." kann man selbstverständlich rausmachen.
"select id,*" - das * war nur zu anschauung. Ich würde auch nur die Felder wählen, die ich wirklich benötige.

Das mit der Fetch Funktion habe ich versucht. Entweder habe ich nicht verstanden wie es richtig geht, oder es geht nicht. Die Funktion wäre schon nice gewesen. Dann könnte ich mir den unteren code sparen; Weil dieser soll ja die Datensätze abschnittsweise einlesen. Aber ich denke, es lohnt sich, mich damit mal ausführlich auseinanderzusetzen.

Das mit .RecordCount habe ich rausgenommen. Ich dachte mit RecordCount wird die maximaldatensätzeanzahl angezeigt. Mit .RecNo wird die aktuelle Datensatz Nr angezeigt?

Hier der neue Code:

Delphi-Quellcode:
var
temp , stop, stopz, a: integer;

begin
// temp ist der "eigene Datensatz Zähler"
//temp := 0; //Anfang der ID's
stop := 0;

      ZQuery3.Close;
      ZQuery3.SQL.Clear;
      ZQuery3.SQL.Text := 'select min(id) as mm from tabelle1;';
      ZQuery3.Open;
      temp := StrToInt(ZQuery3.FieldByName('mm').AsString);

   ZQuery3.Close;
   ZQuery3.SQL.Clear;
   ZQuery3.SQL.Text := 'select max(id) as mm from tabelle1';
   ZQuery3.Open;
   stopz := ((StrToInt(ZQuery3.FieldByName('mm').AsString)-2));



 while stop = 0 do begin //Datensätze nur abschnittsweise laden
   ZQuery1.Close;
   ZQuery1.SQL.Clear;
   ZQuery1.SQL.Text := 'select id,* from tabelle1 where id >= "'+IntToStr(temp)+'" Limit 100;'; // Limit 100: Ggf. verkleinern
   ZQuery1.Open;


   if (stopz <= temp) then begin stop :=1; exit; end; // Wenn Ende erreicht von DB, dann Schleife beenden


  for a := 0 to stopz do begin
  // *** Hier die einzelnen Datensätze verarbeiten ***
  end; //for

temp := temp+100; // muss gleich sein wie bei Limit oben
 end; //while



end;

p80286 4. Aug 2018 22:49

AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
 
Delphi-Quellcode:
var
  firstid : integer; // ggf cardinal oder int64
  alldone : boolean;
begin
  alldone:=false;
  firstid:=0; // Annahme die IDs sind alle größer als 0
  ZQuery1.Close;
  ZQuery1.SQL.Text := 'select id chkid,* from tabelle1 where id >= :minid order by id Limit 100;';
  repeat
    Zquery.Parameters.ParambyName('minid').asinteger:=firstid;
    ZQuery1.Open;
    zQuery1.First;
    if not zquery1.EOF then
    begin
      repeat
        firstid:=Zquery1.Fieldbyname('chkid').asinteger;
        //mach was mit dem Datensatz
        Zquery1.next;
      until Zquery1.EOF;
    end
    else
    begin
      // alle Datensätze sind verarbeitet
      alldone:=true;
    end;
    ZQuery1.close;
    inc(firstid);
  until alldone;
end;
Die Syntax mußt Du noch prüfen da ich ZEOS nicht so genau kenne.
Aber damit solltest Du das erreichen was Du willst.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:11 Uhr.
Seite 3 von 3     123   

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