# Datenbank Abfragen mit großen Datenmengen



## Sauerkraut (4. Feb 2008)

Hallo,

ich führe in Java eine Abfrage an einer Datenbank mithilfe eines SQL Strings aus. Alleerdings kommt hat das Ergebnis mehr als eine Million Datensätze. Damit bekomme ich Probleme mit meine Java Heap Space, ich habe ihn schon versucht zu vergrößeren, trotzdem erhalte ich eine Exception das der Speicher zu klein ist.

java.lang.OutOfMemoryError: Java heap space

Wie muss man in Java mit solchen Datenmengen umgehen?


----------



## ms (4. Feb 2008)

Was willst du denn mit diesen >1Mio Datensätze anstellen?

ms


----------



## Gelöschtes Mitglied 5909 (4. Feb 2008)

da musst du wohl auf die hdd streamen


----------



## maki (4. Feb 2008)

... oder genauere und daher bessere Abfragen formulieren, es ist eher selten, das man wirklich so viele Datensätze benötigt.


----------



## HeRaider (4. Feb 2008)

Ist doch logisch, dass es da Probleme gibt. Ich würde mal grob schätzen, dass das mit dem restlichen Programm locker mal 500-1000MB sind die dann im Arbeitsspeicher landen müssten. Daher also wie raiL schon gemeint hat ab auf die Festplatte damit und dann einfach Datensatz für Datensatz aus der Datei lesen und verarbeiten.


----------



## Guest (4. Feb 2008)

Ok... nur kurz zur Info...

Ich weiß das es im ersten Moment nicht sinnig ist, aber trotzdem muss es theoretisch gehen. Ich hab einfach soviele Daten in meiner Datenbank und die möchte ich unter bestimmten Umständen auch alle anzeigen lassen. Warum ist mal dahin gestellt, aber die ganze Admin GUI Tools kriegen das auch hin.


----------



## ms (4. Feb 2008)

Ich kenne kein Tool das 1Mio Datensätze auf einmal darstellt. Höchstens über eine Blätterlogik 20, 30, 50, 100 ... Datensätze pro Seite anzeigt. 

ms


----------



## Mork (4. Feb 2008)

> Ich weiß das es im ersten Moment nicht sinnig ist, aber trotzdem muss es theoretisch gehen. Ich hab einfach soviele Daten in meiner Datenbank und die möchte ich unter bestimmten Umständen auch alle anzeigen lassen.


Kannst du die Datensätze nicht nacheinander holen? 1Mio Datensätze kann man eh nicht gleichzeitg anschauen, auch nicht mehr einem Admin GUI Programm.


----------



## Sauerkraut (4. Feb 2008)

Ich verwende als Datenbank Postgre und den dazu gehörigen pgAdmni Query... mit dem kann ich tatsächlich weit mehr als eine Millionen Datensätze abfragen und auch anzeigen lassen. Und das auch ziemlich flott, ohne blättern oder warten.

Im Speicher werden dafür nicht mehr als 150MB verwendet.

Und das richtig Tolle ist, man kann es auch von dort exportieren.

Warum sollte man das über eine Java Applikation nicht auch hinbekommen?


----------



## Jockel (4. Feb 2008)

Das möchte ich sehen, dass 1 Million Datensätze GLEICHZEITIG auf dem Bildschirm dargestellt werden. Alles andere lässt sich durch nachladen der Daten bewerkstelligen.


----------



## Sauerkraut (4. Feb 2008)

Zumindest nicht gleichzeitig auf dem Bildschirm, aber man kann ganz bequem runterscrollen und das beliebig schnell und das in der Zwischenzeit nachgeladen wird. Die Abfrage dauert ca. 3 Minuten, danach kann man ganz bequem mit den Daten arbeiten.


----------



## Mork (4. Feb 2008)

Glaube trotzdem nicht, dass die Daten dann komplett im Hauptspeicher liegen. Viel eher werden dann Hashtabellen oder sonstige Indexstrukturen erstellt, dass es beim Scrollen so aussieht, als ob nicht nachgeladen wird.


----------



## Guest (4. Feb 2008)

Ok... wie kann man sowas dann in Java bewirken, mehr will ich doch gar nciht wissen....


----------



## maki (4. Feb 2008)

> Zumindest nicht gleichzeitig auf dem Bildschirm, aber man kann ganz bequem runterscrollen und das beliebig schnell und das in der Zwischenzeit nachgeladen wird.


Offensichtlich werden nicht 1 Mio Datensätze gleichzeitig geladen (wäre auch ziemlich bescheuert wenn es um die Anzeige am Bildschirm geht).

Das kannst du doch nachbauen.


----------



## Mork (4. Feb 2008)

Du kannst das Ergebnis ja limitieren. Dann holst dir die Datensätze 1 bis 10 der Anfrage, dann 11 bis 20 usw. In MySQL nennt sich die Funktion limit.


----------



## Guest (4. Feb 2008)

Also von der Performance kann ich es nur noch mal wiederholen, dass das Tool einmal die Abfrage startet (dauert ca. 3 min) und man danach wunderbar durch die Datensätze scrollen kann, ohne das er was nachladen muss. Man kann das auch wunderbar an der Rechenauslastung überprüfen. Das heißt er muss irgendwo die Daten zwischengelagert haben und schnell abrufen können.


----------



## sparrow (4. Feb 2008)

Die Datenbank kann sie doch auch vorhalten....
Wie genau rufst du denn das ResulSet ab? Einfach einmal komplett durch und irgendwo in eine Collection geschrieben? Das ist vielleicht nicht die beste Idee.

Ich habe mit PostgreSQL folgende Erfahrungen gemacht:
Auch sehr große Datenmengen lassen sich problemlos abarbeiten.
Deine Abfrage landet doch eh nicht auf einmal bei dir, sondern nur das wo der Zeiger auf den Datensätzen steht.
Ich nehme an du hast eine Order oder Group-Klausel in deiner Abfrage.

Wie gesagt, Limit ist prima zum eingrenzen der Datensätze, ansonsten kannst du dir auch überlegen ob du das ResulSet solange offen lässt und mit dem Zeiger nach und anch durch die Datensätze wanderst. Das ist allerdings nicht besonders schön.


----------



## happy_robot (4. Feb 2008)

das grösste problem scheint mir hier die suche eines passenden bildschirms zu sein welcher 1Mio-datensätze tatsächlich gleichzeitig darstellen kann...   

ansonsten ist das "abholen" dieser anzahl datensätze auf einen rutsch wohl nichts anderes als ein denkfehler, die unkenntnis der möglichkeiten der replikation, oder einfach mangelnde SQL-Kenntnisse.


----------



## Sauerkraut (5. Feb 2008)

Es geht mir nicht darum sie gleichtzeitig darzustellen, sondern nur um das Prinzip damit zu arbeiten, ohne das man es nachladen muss.

@Happy Robot: Bevor du große Reden schwingst und Begriffe in die Welt setzt, solltest du lieber Lösunvorschläge bringen oder einfach ruhig sein.


----------



## DP (5. Feb 2008)

happy_robot hat gesagt.:
			
		

> die unkenntnis der möglichkeiten der replikation, oder einfach mangelnde SQL-Kenntnisse.



was hat denn das eine mit dem anderen zu tun?! replikation ist hier völlig irrelevant


----------



## ARadauer (5. Feb 2008)

ich hatte mal ein Tutorial, wo sowas beschrieben wird. Ich muss zuhause nachschaun, ich poste am Abend den link.

Es ging ungefähr so... Es werden ca 100 Zeilen geladen, wird bis zur Zeile 80 gescrollt, werden die nächsten 100 geladen, damit das schön flüssig ist. Die Werte werden in ein einer Arraylist gehalten. Sind mehr als 500 Zeilen geladen, werden alte Zeilen verworfen... 

Man mus sich ja nur das JTableModel ansehen, was braucht man? Die Anzahl der Zeilen, die kann man sich über ein count oder sonst was hohlen. Und dann eine Möglichkeit bestimmte Zeilen zurück zugeben und diese und +- 50 andere lädt man wenn sie nicht vorhanden ist.

Wie gesagt, ich werde das Tutorial am Abend posten. Ausser ich betrink mich heute total, dann mach ichs morgen..... ;-)


----------



## robertpic71 (5. Feb 2008)

Da gibt es ein Reihe von Möglichkeiten:

1.) ResultSet Type ändern 
Teste einmal

```
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
```
Per Default wird das ResultSet komplett gepuffert. Diese Einstellungen sollten dem JDBC-Treiber signalisieren, dass das nicht macht. Sollte normalerweise auch bei PostgreSQL funktionieren.

2a. Mit LIMIT und OFFSET arbeiten

```
SELECT * FROM table LIMIT 10000 OFFSET 20000
```
Damit kann man sich die Tabelle in kleineren Scheiben holen.

LIMIT = Anzahl der zu lesenden Sätze
OFFSET = Anzahl der zu überlesenden Sätze

Also z.B.
.. LIMIT 10000 OFFSET 0
.. LIMIT 10000 OFFSET 10000
.. LIMIT 10000 OFFSET 20000
...

Die LIMIT und OFFSET sind aber keine Standard-SQL-Befehle. PostgreSQL kann sie, aber andere Datenbanken ev. nicht.

Variante a.)
Die GUI-Komponente mit allen Sätzen "vollknallen".

Variante b.)
Das Scrollevents abfragen und immer hinten Sätze dazulesen. Hier wäre ein kleineres Limit z.B. 50-500 sinnvoll.

Variante c.)
Die Daten in einen serializierbare Form bringen (z.B. ArrayList, RowSet oder CachedRowSet) und die GUI von dort bedienen.

3.) Mit Stored Procedures arbeiten
Hier wird der Cache auf der Serverseite angelegt. Die Definitionen der stored Procdures 
gehen bei den Datenbanken ziemlich auseinander. Da kann ich (für PostgreSQL) nicht mit einem Beispiel dienen.

/Robert


----------



## Sauerkraut (5. Feb 2008)

Danke für die Übersicht der Möglichkeiten. Damit kann ich was anfangen.


----------

