AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

OutOfMemory Fehler abfangen

Ein Thema von Aviator · begonnen am 30. Jul 2016 · letzter Beitrag vom 2. Aug 2016
Antwort Antwort
Seite 1 von 3  1 23   
Aviator

Registriert seit: 3. Jun 2010
1.588 Beiträge
 
Delphi 10.3 Rio
 
#1

OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 00:57
Hallo zusammen,

aktuell stehe ich vor dem Problem, dass ich sehr sehr sehr viele Datensätze aus einer SQLite Datenbank laden muss. An dieser Stelle kann ich auch nichts ändern, da der User explizit so viele Datensätze anfordert. Kann also in dem Fall nicht virtuell arbeiten. In gewissem Maße wird das sogar schon gemacht, da mit dem VirtualTreeView gearbeitet wird. Die Daten werden im Hintergrund in einer komplexen Datenstruktur vorgehalten.

Das Problem ist jetzt, dass bei so vielen Datensätzen der nutzbare Arbeitsspeicher für das Programm ausgeht (32-bit Anwendung). Bei 64-bit kein Problem. Jetzt stelle ich mir nur die Frage, wie ich einen solchen Fehler abfangen kann. Ich merke ja erst dann wenn die Exception ausgelöst wird, dass der Arbeitsspeicher voll gelaufen ist. Nachdem die Exception ausgelöst wurde, kann ich aber meine Struktur im Hintergrund nicht mehr freigeben um nochmal etwas Arbeitsspeicher frei zu machen. Die Folge wenn ich das mache ist, dass die nächste Exception mit OutOfMemory ausgelöst wird.

Wie macht ihr sowas oder kann man das überhaupt abfangen? Falls ihr noch Informationen braucht, dann kann ich euch die gerne geben. Es sei denn es wäre SourceCode. Da müsste ich schauen, was ich veröffentlichen kann. Aktuell geht es mir aber erstmal um das generelle OutOfMemory Problem.
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#2

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 03:11
Zitat:
kann ich aber meine Struktur im Hintergrund nicht mehr freigeben
Kann man immer an der richtigen stelle.
Wenn die aktuelle Datenbank nicht mehr verwendet wird (Aber ich denke das tust du bereits)

Das Problem ist nur wenn die Datenbank so groß ist das sie den verfügbaren Speicher sprengt und du zu der zeit nur mit einer arbeitest
was will man dann freigeben wenn sie gerade in gebrauch ist.

Was ich mir vorstellen könnte die Datenbank zu splitten und den gerade nicht verwendeten Teil davon freizugeben.
Also eine Datenbank in kleinere Häppchen aufteilen.

gruss
  Mit Zitat antworten Zitat
Benutzerbild von sh17
sh17

Registriert seit: 26. Okt 2005
Ort: Radebeul
1.558 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 06:51
Würde mich auch interessieren, hab das gleiche Problem nämlich beim Drucken unter Nutzung von GDI+. Würde sich das bei Win64 dann erledigen? Konnte ich noch nicht prüfen.
Sven
--
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
909 Beiträge
 
Delphi 6 Professional
 
#4

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 10:36
Hmm..

Bei so vielen Daten solltest Du Dir vielleicht auch Gedanken über ein anderes DB-System machen...

Z.B. gibt/gab es bei ADO die Möglichkeit mit CursorLocation=clUseServer die Daten Sequentiell ab zu rufen..

In Verbindung mit einem SQL-Server hat dies dazu geführt, das die Datenmenge immer nur einen Teil geladen hat und erst beim Scrollen z.B. im DBGrid den nächsten Teil nachgeladen hat.

Dies kannst Du natürlich auch selber Programmieren...
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.588 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 11:10
Würde mich auch interessieren, hab das gleiche Problem nämlich beim Drucken unter Nutzung von GDI+. Würde sich das bei Win64 dann erledigen? Konnte ich noch nicht prüfen.
Also bei 64-bit hast du ja viel mehr Arbeitsspeicher zur Verfügung. Von daher sind dort dann solche Probleme weg. Ich weiß nur nie genau, ob man beim Umstieg von 32-bit auf 64-bit an der Art der Programmierung (Datentypen usw.) etwas ändern muss bzw. sollte.

Bei so vielen Daten solltest Du Dir vielleicht auch Gedanken über ein anderes DB-System machen...
Das ist leider nicht möglich. Ich schreibe aktuell ein Programm, dass eine SQLite Datenbank auslesen kann. Also eine Art Management Studio für SQLite. Bevor du (oder jmd. anderes) allerdings sagt, dass es solche Programme schon zu genüge gibt: Ich weiß das. Aber ich würde trotzdem gerne ein eigenes schreiben.

Mein Programm funktioniert ja auch schon, aber es gibt bei so viele Datensätzen eben Speicherprobleme. Allerdings nur in Verbindung mit Strings. Wenn nur Zahlen o.ä. in der Abfrage enthalten sind, dann sind 10Mio Datensätze auch kein Problem.

Ein virtuelles Auslesen der Datenbank ... keine Ahnung wie das gehen soll. Zumindest nicht, ohne jetzt mein komplettes Konzept über den Haufen zu werfen. Das war schon sehr kompliziert, überhaupt eine Struktur zu entwickeln um alle Daten darin zu speichern. Wer genaueres Wissen will, sollte sich das Thema SQLite Typaffinitäten auf der SQLite HomePage anschauen.

Zitat:
kann ich aber meine Struktur im Hintergrund nicht mehr freigeben
Kann man immer an der richtigen stelle.
Wenn die aktuelle Datenbank nicht mehr verwendet wird (Aber ich denke das tust du bereits)
Tja die Datenbank selbst ist ja nicht das Problem. Das ist ja nur ein einziger Pointer der von einer DLL zurückgegeben wird. Problematisch sind die Queries die ausgeführt werden. Aber auch nur die, die der User ausführen kann, weil dort zu viele Datensätze zurückkommen könnten.

Wenn ich jetzt ein SELECT * FROM Daten mache und ein LIMIT 1000 vergesse, dann können da je nach Tabelle viele viele Datensätze zurückkommen. Und das weiß ja auch mein Programm vorher nicht. Es sei denn ich würde einen entsprechenen Count vorher ausführen. Aber dann weiß ich immer noch nicht, wie viel RAM die Daten belegen würden.


Es muss doch eine Möglichkeit geben, aus dem Teufelskreis wieder herauszukommen. Ich kann die Exception ja abfangen, aber jegliche weitere Aktion die ich dann ausführen will, führt zu einer weiteren EOutOfMemory Exception. Könnte ich an der Stelle, ander die Exception ausgelöst wird meine Daten die ich aus der Datenbank ausgelesen habe wieder freigeben, dann wäre das kein Problem. Aber zum Freigeben wird anscheinend auch etwas Speicher benötigt, was dazu führt das es nicht mehr funktioniert. Ich kann nicht mal mehr den User mit einer etwas freundlicheren Meldung informieren. Dafür ist auch kein Speicher mehr frei. Und das Programm selbst muss danach auch über den Taskmanager beendet werden, da es sich mit der Meldung OutOfMemory nicht mehr beenden lässt.

Geändert von Aviator (30. Jul 2016 um 11:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
16.910 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 11:49
In Verbindung mit einem SQL-Server hat dies dazu geführt, das die Datenmenge immer nur einen Teil geladen hat und erst beim Scrollen z.B. im DBGrid den nächsten Teil nachgeladen hat.
Du weißt aber schon das damit der Server sehr stark belastet wird. Die 2 GB die du nicht mehr auf Clientseite hast muss der Server verwalten.
Und schneller wird die Lösung nicht wenn man meint Mio. Datensätze in einem Grid zu haben.

Wir haben eine Lösung implementiert zuerst nur die Primärschlüsselspalten zu laden und erst bei der Anzeige die weiteren Spalte nachzuladen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 12:12
Der Anwender tippt ein
SQL-Code:
select *
from hugetable
dein Programm führt aus
SQL-Code:
select * from (
  select *
  from hugetable
) limit 1000 offset 0
Schon gibt es immer nur max. 1000 Zeilen, egal was der Benutzer dort eintippt
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.588 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 16:35
Der Anwender tippt ein
SQL-Code:
select *
from hugetable
dein Programm führt aus
SQL-Code:
select * from (
  select *
  from hugetable
) limit 1000 offset 0
Schon gibt es immer nur max. 1000 Zeilen, egal was der Benutzer dort eintippt
Ja die Idee hatte ich auch schon, aber wie setze ich das am Besten um? Ich muss ja dann immer die Daten aus dem zurückgegebenen ResultSet auslesen und an die bereits ausgelesenen Datensätze anhängen wenn der User im Ergebnisbaum scrollt. Es würde zwar sehr lange dauern bis der User ganz unten ankommt, aber theoretisch könnte der Fehler dann ja immer noch auftreten. Die bereits ausgelesenen Datensätze löschen und die Liste immer von vorne füllen ... ich weiß nicht. Ich muss ja auch den Ergebnisbaum so aufbauen, dass der wenigstens so aussieht, als wären 100.000 Datensätze geladen. Dann müsste ich mir ja auch noch merken, wie weit ich bereits war. OK das wäre das Offset das du in deinem Statement beschreibst.

Kannst du das vielleicht noch etwas genauer ausführen?
  Mit Zitat antworten Zitat
mensch72

Registriert seit: 6. Feb 2008
829 Beiträge
 
#9

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 16:53
in jeder vernünftigen DB-Struktur wird es ja einen PrimaryKey geben, also was spricht dagegen zunächst mal kein
Code:
select * from hugetable
sondern nur ein
Code:
select indexfield from hugetable
zu machen?



Wenn da auch 1mio als ResultSet zurückkommt wird das noch locker in den RAM passen.

Bei der Anzeige(funktioniert super in Grids&VST) wird dann "alles" LineByLine einzeln bei bedarf per separater Query abgefragt und live angezeigt/ausgewertet. Da ist zunächst stets etwas langsamer in Anzeige und Scroll, dafür aber absolut konstant im Verhalten bei quasi beliebig vielen Daten, was der SQL-Server eben hergibt.

Code:
select * from hugetable where indexfield='IndexValue'
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.588 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: OutOfMemory Fehler abfangen

  Alt 30. Jul 2016, 17:32
in jeder vernünftigen DB-Struktur wird es ja einen PrimaryKey geben, also was spricht dagegen zunächst mal kein
Code:
select * from hugetable
sondern nur ein
Code:
select indexfield from hugetable
zu machen?
Halte ich jetzt nicht für die optimale Idee. In diesem Fall müsste z.B. immer eine Verbindung zur Datenbank bestehen. Wenn diese auf einem Netzlaufwerk liegt, kann es auch schonmal vorkommen, dass das Netzwerk nicht funktioniert. In dem Fall wäre ich bei deiner Lösung in den aktuell angezeigten Zeilen gefangen. Mit meiner Lösung könnte ich weiterhin alle Daten durchsuchen, scrollen und bspw. auch kopieren.

Gibt es denn keine Möglichkeit, ein OutOfMemory Fehler abzufangen und die Instanzen wieder freizugeben die den Speicher belegen?
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 17:04 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf