AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Große Datenmengen richtig verarbeiten bzw. Out of Memory
Thema durchsuchen
Ansicht
Themen-Optionen

Große Datenmengen richtig verarbeiten bzw. Out of Memory

Ein Thema von Monday · begonnen am 10. Jul 2018 · letzter Beitrag vom 4. Aug 2018
Antwort Antwort
Seite 1 von 3  1 23      
Monday

Registriert seit: 24. Aug 2012
103 Beiträge
 
FreePascal / Lazarus
 
#1

Große Datenmengen richtig verarbeiten bzw. Out of Memory

  Alt 10. Jul 2018, 07:27
Datenbank: SQLite • Version: 3 • Zugriff über: ZEOS
Hallo,

ich habe eine große Datenbank ( > 1 Mil. Datensätze ) und möchte die einzelnen Datensätze einzeln weiterverarbeiten.
Bei kleineren Datenmenge habe ich mir nie Gedanken über select & co gemacht. Bei größeren Datenmenge bekomme ich regelmäßig "Out of Memory" Probleme (Nicht zuletzt wegen geringen Arbeitsspeicher (4 GB)). Einzige Möglichkeit sehe ich, die Datensätze nur Häppchenweiße einzulesen. Schön finde ich das allerdings nicht, wie ich finde.

Gibt es noch effektivere Möglichkeiten als diese hier? Hier mein Grundgerüst:

Delphi-Quellcode:

var
temp , stop, a: integer;

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

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



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

   Form1.ZQuery3.Close;
   Form1.ZQuery3.SQL.Clear;
   Form1.ZQuery3.SQL.Text := 'select max(id) as mm from tabelle1';
   Form1.ZQuery3.Open;
   if (((StrToInt(Form1.ZQuery3.FieldByName('mm').AsString)-2)) <= temp) then begin stop :=1; exit; end; // Wenn Ende erreicht von DB, dann Schleife beenden


  for a := 0 to ZQuery1.RecordCount-1 do begin
  // *** Hier die einzelnen Datensätze verarbeiten ***
  end; //for


 end; //while



end;
Liebe Grüße
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.858 Beiträge
 
Delphi 11 Alexandria
 
#2

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

  Alt 10. Jul 2018, 08:13
In diesem Code liegt viel im Argen.

Warum die Verweise auf eine Instanz eiesn Formulars (Form1). Wo steht dieser Code in Form1 oder in einem anderen Formular?

Was für einen Typ hat das Feld ID? Warum fragst Du es als String ab und wandelst es dann in einen Integer?
Warum fragst Du nicht am Anfang ab, was das Maximum ist sondern bei jedem Schritt?
Welches DBMS?
Warum keine parametrisierte Abfrage?
Markus Kinzler

Geändert von mkinzler (10. Jul 2018 um 09:03 Uhr)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#3

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

  Alt 10. Jul 2018, 09:11
Hallo,

Delphi-Quellcode:
for a := 0 to ZQuery1.RecordCount-1 do begin
  // *** Hier die einzelnen Datensätze verarbeiten ***
  end; //for
select id,*
Brauchst Du wirklich alle Felder der Tabelle?

Das könnte schon das Problem sein.
Hier werden ja nach DB alle Datensätze lokal heruntergeladen und zwischengespeichert.
Ändere das mal ab.

Delphi-Quellcode:
ZQuery1.UniDirectional:= True;
while not ZQuery1.Eof do
begin
  // Datensatz verarbeiten

  ZQuery1.Next;
end;
Heiko
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

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

  Alt 10. Jul 2018, 09:21
Wenn zu viele Daten von der DB zurück geliefert werden, warum arbeitest Du dann mit
'select id,* from tabelle1 where id ... Zumindest das Feld ID ist dann doppelt.

Wenn Du schon ID zu irgendwelchen Berechnungen und Vergleichen benutzt (-2,<=), dann solltest Du wenigstens eine auf- oder absteigende Reihenfolge sicherstellen
order by id asc/desc Über einen Integer der als Boolean mißbraucht wird, möchte ich mich nicht weiter auslassen.

Und wenn Du min(ID) bzw. max(ID) benötigst, dann kannst Du das zu Anfang Deiner Verarbeitung abfragen, und mußt nicht die ganze Zeit eine Connection offen halten.

Gruß
K-H

Edith:
nach dem Abholen der Datensätze muß der .RecordCount nicht zwangsläufig korrekt sein.
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector

Geändert von p80286 (10. Jul 2018 um 09:24 Uhr)
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#5

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

  Alt 10. Jul 2018, 09:23
Die Frage wäre auch, was die Verarbeitung macht?
z.B.
- Selektierte Daten ändern
- neue erzeugen / ggF. in andere Tabelle
- irgendwas zählen
?

Viele solcher Maßnahmen können durch SQL erledigt werden, ohne dass man überhaupt Daten aus der DB lokal holt.

Ist es nichts von dem oben, sondern -sagen wir mal- ein kleiner Datenabgleich und speichern eines Resultats in einer Datei, könnte man den Datenzugriff schlanker gestalten, Stichwort unidirektionale Cursor, Readonly, etc..
Ich weiß allerdings nicht, was die sqlite clients da können.
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#6

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

  Alt 10. Jul 2018, 10:55
Ich hoffe SQLite kann das und ZEROS sollte auch eine Fetch-Funktion bieten,
also wo das DataSet nicht alle Daten runterläd, sondern nur ein Fenster/Teil des ganzen ResultSets.

http://zeoslib.sourceforge.net/viewtopic.php?t=20005
http://forum.lazarus.freepascal.org/...?topic=13192.0

Wenn nicht, dann mußt du das eben selber implementieren, die Abfrage mehrmals mit LIMIT/OFFSET ausführen und die Daten stückchenweise holen.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#7

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

  Alt 10. Jul 2018, 12:06
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. Auf diese Weise lassen sich Datenmengen sehr effizient abrufen. (In meinem Fall ging es um threadbasierte Verarbeitung von Teilmengen.)

Edith:
nach dem Abholen der Datensätze muß der .RecordCount nicht zwangsläufig korrekt sein.
Nicht nur das, der Abruf bewirkt auch, dass sofort alle Datensätze von der Datenbank abgeholt werden, auch wenn das an der Stelle eigentlich gar nicht nötig wäre. Dadurch dauert der Start der Verarbeitung unnötig lange.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
freejay

Registriert seit: 26. Mai 2004
Ort: Nürnberg
272 Beiträge
 
Delphi 11 Alexandria
 
#8

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

  Alt 10. Jul 2018, 17:30
Leider kenne ich ZEOS nicht und mit SQLite habe ich auch noch nicht viel gemacht.

Wenn es MySQL wäre und Du die MyDac-Komponenten benutzen würdest, müsste man dort nur FetchAll auf false und UniDirectional auf True setzen, dann wird immer nur die unter FetchRows angegebene Anzahl von Datensätzen im Speicher gehalten und man kann mit einer einzigen While-Schleife beliebig große Datenbanktabellen oder Query-Ergebnisse durchlaufen. Keine Gefahr von Out-Of-Memory.

Vielleicht gibt es ja bei ZEOS & SQLite ähnliche Optionen?
[Delphi 11.3.1 Enterprise; Win10/11; MySQL; VCL]
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.275 Beiträge
 
Delphi 10.4 Sydney
 
#9

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

  Alt 11. Jul 2018, 07:01
Hallo,

Zitat:
FetchAll auf false und UniDirectional auf True
wie ich schon weiter oben geschrieben hatte.
(FetchAll ist standardmäßig ausgeschaltet und sollte nur aus Kompatibilitätsgründen zum Bsp. für den BDE-Ersatz benutzt werden).
Heiko
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#10

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

  Alt 11. Jul 2018, 09:09

Delphi-Quellcode:
ZQuery1.UniDirectional:= True;
while not ZQuery1.Eof do
begin
  // Datensatz verarbeiten

  ZQuery1.Next;
end;
Das Setzen von UniDirectional auf True muss vor dem Öffnen (ZQuery1.Open) der Abfrage erfolgen, danach ist es "zu spät", wenn ich mich nicht irre?
Michael Justin
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 14:03 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