![]() |
Datenbank: SQLite • Version: 3 • Zugriff über: ZEOS
Große Datenmengen richtig verarbeiten bzw. Out of Memory
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:
Liebe Grüßevar 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; |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
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? |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
Hallo,
Delphi-Quellcode:
select id,*
for a := 0 to ZQuery1.RecordCount-1 do begin
// *** Hier die einzelnen Datensätze verarbeiten *** end; //for 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; |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
Wenn zu viele Daten von der DB zurück geliefert werden, warum arbeitest Du dann mit
SQL-Code:
Zumindest das Feld ID ist dann doppelt.
'select id,* from tabelle1 where id ...
Wenn Du schon ID zu irgendwelchen Berechnungen und Vergleichen benutzt (-2,<=), dann solltest Du wenigstens eine auf- oder absteigende Reihenfolge sicherstellen
SQL-Code:
Über einen Integer der als Boolean mißbraucht wird, möchte ich mich nicht weiter auslassen.
order by id asc/desc
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. |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
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. |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
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. ![]() ![]() Wenn nicht, dann mußt du das eben selber implementieren, die Abfrage mehrmals mit LIMIT/OFFSET ausführen und die Daten stückchenweise holen. |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
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.)
Zitat:
|
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
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? |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
Hallo,
Zitat:
(FetchAll ist standardmäßig ausgeschaltet und sollte nur aus Kompatibilitätsgründen zum Bsp. für den BDE-Ersatz benutzt werden). |
AW: Große Datenmengen richtig verarbeiten bzw. Out of Memory
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz