Speicherproblem ;)


wakoz

Erfahrenes Mitglied
#1
Hi ho

Ich habe ein Kleines Speicherproblem und hoffe ihr könnt Helfen.

Ich Frage von einer Oracle DB eine Tabelle ab, das Problem die Tabelle ist etwas größer und das Array was ich mittels JDBC zurück bekomme ist sehr groß für den Arbeitsspeicher. Nicht unbedingt direkt nach der DB Antwort, aber wenn ich das Array verarbeite habe ich schnell das Array bzw den Inhalt mehrfach im Speicher.

Meine Idee war entweder vor dem auslesen des Arrays aus der DB oder direkt danach die Datenmenge zu ermitteln. Also wenn das Array 100MB groß wird soll es nicht ausgelesen werden oder nicht weiter verarbeitet.
Die Schwierigkeit dabei, das Programm (ein Servlet) Läuft auf einen Server Welcher Zeitgleich mehrere abfragen bearbeiten muss und ich nicht einfach den Speicher Auslastung beobachten kann.

Zusammen gefasst: ;) gibt es eine Möglichkeit DB Seitig die Ergebnis Größe vorher abfragen kann? Oder gibt es die Möglichkeit die Daten Menge eines Java Objektes zu erfahren?

Erschwert wird es vielleicht auch dadurch das ich derzeit nur Java 1.4 verwende ein Upgrade ist geplant aber das könnte noch dauern.

MfG und Danke
 
#2
Verwende doch einfach die LIMIT-Clausel in deinem Query um die Tabelle blockweise auszulesen. Dabei solltest du beim Ermitteln eines günstigen Limits vom WORST-CASE ausgehen, also das das Array die maximale Größe erreicht. davon ziehst du noch gut 10% Sicherheit ab und hast so ein LIMIT welches dir z.B. im WORST-CASE nur ein Array von 30MB zurück gibt.
Da LIMIT zwei Parameter *einen Startindex und einen Endindex* hat lässt sich damit sehr einfach die Tabelle stückenweise auslesen. So hast du genug Zeit erst alles aufzuräumen und genug Speicher freizumachen bevor du den nächsten Block liest und verarbeitest. Das dadurch natürlich ein geringer Overhead entsteht da du ja mehrere Anfragen an die DB sendest sollte dabei allerdings vernachlässigbar sein.
 

wakoz

Erfahrenes Mitglied
#3
A Litle Bit too much xD

Das Ganze soll über Servlet verbreitet werden und da ist es nicht der Sinn große Daten Mengen zu versenden bzw wenn ich ein respose gemacht hab ist die Verbindung fürs erste futsch.

Wobei es doch klappen kann, ich sende ein Limit mit und wenn ich Scheiben Antworten bekomme Schmeiße ich eine Exception und vergesse die Antwort.
 
#4
FAIL

Das LIMIT hat doch nichts mit der Verbindung CLIENT-ServletServer zun tun sondern mit der Verbindung Servlet-Datenbank. Und diese bleibt ja wohl so lange bestehen bis du sie entweder closed oder der Server sie gewaltsam resetet weil da Timeout erreicht wurde.
 

wakoz

Erfahrenes Mitglied
#5
FAIL

Das LIMIT hat doch nichts mit der Verbindung CLIENT-ServletServer zun tun sondern mit der Verbindung Servlet-Datenbank. Und diese bleibt ja wohl so lange bestehen bis du sie entweder closed oder der Server sie gewaltsam resetet weil da Timeout erreicht wurde.
is schon klar, nur bekomme ich keinen Speicher frei wenn ich nicht zuvor via limit abgefragte Daten weg schicke und da kommt dann die Client Server Verbindung ins Spiel :(

Aber wie gesagt das Servlet soll nicht Große Daten Pakete versenden, wenn eine DB Antwort zu groß wird soll das Servlet die Verarbeitung der Daten verweigern.
 
#6
Dann nutz doch SQL-Befehle wie LENGTH().
Daimt kannst du ein SQL-Query bauen der dir die Größe der Datensätze liefert. Das returned ResultSet ist auf Grund des primitiven Typs *int* auch bei großen Tabellen noch relativ klein. Du kannst dann einfach durch das ResultSet iterieren und die Datensatzgrößen zusammen rechnen. Ist dir das Ergebnis dann zu groß brichst du das Servlet mit einer Fehlermeldung für den Browser ab. Ansonten stellst du dann das Query um an die Daten zukommen.
Ein kombination beider Queries in einem ist soweit ich weis nicht möglich da du innerhalb eines SQL-Statements mit LENGTH() wenn überhaupt nur die Größe eines Datensatzes eines Feldes bekommst. Das musst du dann im Servlet zusammenrechnen und prüfen.
 

j2se

Erfahrenes Mitglied
#7
Ich Frage von einer Oracle DB eine Tabelle ab, das Problem die Tabelle ist etwas größer und das Array was ich mittels JDBC zurück bekomme ist sehr groß für den Arbeitsspeicher. Nicht unbedingt direkt nach der DB Antwort, aber wenn ich das Array verarbeite habe ich schnell das Array bzw den Inhalt mehrfach im Speicher.
Versuche Deinen Code derart zu optimieren, dass das Object nur 1x im Speicher angelegt wird.

Also wenn das Array 100MB groß wird soll es nicht ausgelesen werden oder nicht weiter verarbeitet.
Die Grösse des Arrays kann man z.B. mit einer Stored Procedure (welche DB wird benutzt?) auf dem DB-Server errechnen und dann die Grösse zurückgeben lassen. Auf dem Java-Client kann man dann entscheiden, ob man das Array liest oder nicht. Ist das für dich machbar?

Wenn Du mir Deine DDLs/SQLs durchgibst, kann ich auf die Schnelle eine Tabelle erzeugen und einige Tests fahren.
 

Neue Beiträge