DB2 Mit Cursor auf die DB

KimKaze

Aktives Mitglied
Hallo zusammen,

ich Suche nach einer Möglichkeit eine Tabelle mit ca. 3 Mio. Datensätzen auszulesen und diese Zeilenweise in eine csv-datei zu packen.

Mein Anliegen ist es, diese 3 Mio. Sätze so geschickt wie möglich zu laden.
Dass ich in der Where-Bedingung auf ein Feld einschränke und mit mehreren abfragen arbeite
1. Durchlauf - Feld > 0 und < 1000
2. Durchlauf - Feld >= 1000 und < 2000
ist dabei nicht meine Absicht.

Ich arbeite mit Java 1.5.18 und DB2

Zur Zeit lese so:
Java:
String sql= .....
final PreparedStatement stm = conn.prepareStatement(sql);
      try
      {
         final ResultSet rs = stm.executeQuery();
         try
           {
            while (rs.next())
            {
                String str = rs.getString(1);
                String abc = rs.getString(2);
                usw...
            }
          }
       }

Ich schaffe es aber nicht alle Sätze gleichzeitig zu Laden und habe noch keine gute, saubere Lösung gefunden dieses Problem zu umgehen.

Bitte um Hilfe.
 

homer65

Top Contributor
Um welches DB2 handelt es sich denn?
Ich persönlich kenne DB2 z/OS.
Dort gibt es das LOAD Utility, welches darauf spezialisiert ist Daten in eine Tabelle zu laden.
Das sollte man auch benutzen. Ein laden per Java Programm ist ineffektiv.
 

KimKaze

Aktives Mitglied
DB2 z/OS ist korrekt, aber mit der Load Utility kann ich nichts anfangen.
Die Load-Utility lädt die Daten aus einer Tabelle und kopiert/inseriert/verschiebt diese in eine andere. Das ist nicht mein Ziel.

Ich brauche auf jeden Fall die Ausgabe in der csv-datei und ggf. dann noch das zippen.
 
Zuletzt bearbeitet:

tfa

Top Contributor
Warum willst du alle Sätze gleichzeitig laden? Kannst du sie nicht einen nach dem anderen in die csv-Datei speichern?
 

KimKaze

Aktives Mitglied
Wie soll das gehen?
Ich kann die ersten 250.000 ziehen mit fetch first 250.000
Allerdings gibt es nicht sowas wie fetch next 250.000

Daher brauche ich ja den Cursor.
 

KimKaze

Aktives Mitglied
Wenn ich mit select * auf die Tabelle gehe dann werden alle Sätze in das ResultSet geladen...
Dann bekomme ich einen Fehler.. HeapSpace überlaufen da er sich nicht mal eben 3.500.000 Datensätze merken kann.
 

KimKaze

Aktives Mitglied
Ich denke wir reden hier irgendwie aneinander vorbei...
Ich möcht mir eine Tabelle laden und diese in eine CSV-Datei exportieren.

Um dies zu tun muss ich mir im ersten Schritt die Daten laden und dann zeilenweise in eine csv schreiben.
Das laden funktioniert leider nicht da er es nicht schafft alle 3.5 mio Datensätze gleichzeitig zu laden.

Wenn ich mit einem Select * auf die DB gehe dann bekomme ich beim Laden, noch bevor ich ein Ergebnis von der DB bekomme einen HeapSpace überlaufen fehler.

Jetzt Suche ich eine Möglichkeit dies umzusetzen.
 

tfa

Top Contributor
Musst du um die Daten in die Datei zu schreiben, alle 3,5 Mio Sätze gleichzeitig im Arbeitspeicher haben?

Probier doch einfach mal folgendes:
Java:
while (rs.next()) {
    MeinDatensatz data = naechstenDatensatzAusResultsetEinlesen(rs);
    meineCsvDatei.datensatzAbspeichern(data);
}
 

KimKaze

Aktives Mitglied
soweit das ich rs.next sagen kann funktioniert ja schon garnicht.
Denn genau so wie du gerade beschreibst mache ich das ja.

Aber so befinden sich trotzdem alle Datensätze im rs und damit im Arbeitsspeicher.
 

KimKaze

Aktives Mitglied
Java:
      final StringBuffer sb = new StringBuffer();
      sb.append(    " SELECT *  FROM " + schema + "." + tabelle + " WITH ur;");

      final PreparedStatement stm = conn.prepareStatement(sb.toString());
      try
      {
         final ResultSet rs = stm.executeQuery();
         try
         {
            ResultSetMetaData rsMeta = rs.getMetaData();
            writeHeaderFields(writer, rsMeta);
            while (rs.next())
            {
                 String[] str = leseZeile(rs);
                 schreibeInCsv(str)
            }
         }
         finally
         {
            rs.close();
         }
      }
      finally
      {
         stm.close();
      }
 

tfa

Top Contributor
Lass doch mal das "WITH ur" weg. Mein DB2-Buch sagt, dass macht einen Cursor mit abweichendem Isolation Level. Das klingt ungesund bei 3,5 Mio Zeilen.
 

KimKaze

Aktives Mitglied
Es muss ein uncomitted read (also with ur) sein.
Ich mache einen Datenabzug einer oft benutzten Datenbank.
Hier ohne uncomitted read zu lesen, würde heißen, dass ich für die Zeit des lesens die Tabelle für andere sperren würde. Das geht nicht. Es muss während des Auslesens weiter auf die DB zugegriffen werden.
 

tfa

Top Contributor
Ich habe mal ein wenig mit "WITH ur" experimentiert und keinen Grund gefunden, warum es nicht damit auch gehen soll. Meine Riesentabelle mit über 100 Mio Zeilen wird damit auch problemlos eingelesen.

Zeigt doch mal die Exception mit Stacktrace.
 

KimKaze

Aktives Mitglied
Java:
[COLOR="Red"]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.text.DateFormatSymbols.loadZoneStrings(DateFormatSymbols.java:457)
	at java.text.DateFormatSymbols.initializeData(DateFormatSymbols.java:489)
	at java.text.DateFormatSymbols.<init>(DateFormatSymbols.java:103)
	at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:445)
	at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:427)
	at de.rewe.sam.util.Datum.toString_JJJJ_MM_TT(Datum.java:792)
	at de.rewe.sam.tools.tabellenauswertungen.TabellenAuslesen.leseTabelle(TabellenAuslesen.java:188)
	at de.rewe.sam.tools.tabellenauswertungen.TabellenAuslesen.main(TabellenAuslesen.java:83)[/COLOR]
 

tfa

Top Contributor
Da ist aber nichts von executeQuery zu sehen. Du sagtest, in Zeile 7 fliegt der Fehler, also beim Erzeugen des ResultSets.
Speichert "schreibeInCsv" irgendwelche Objekte?
 

KimKaze

Aktives Mitglied
tatsächlich habe ich mir in einer vergessenen Map, aus meiner ersten Version, alles in eine ArrayList gepackt. Diese hat dann den HeapSpace voll laufen lassen.

Scheint zu funktionieren.
Vielen Dank !!!
 

Ähnliche Java Themen


Oben