J
JanB
Gast
Hallo,
da ich mich immer mehr im Kreise drehe, dachte ich mir, frage ich mal die Experten
Folgendes Problem:
Aus einer Oracle-Datenbank bekomme ich einen Clob-Wert, welcher per Java in Token zerlegt werden soll und dann per Array als benutzerdefinierter Oracle-Datentyp zurückgegeben wird. Es werden 366.000 Datensätze übermittelt (kann variieren) und bei der Verarbeitung stosse ich wohl an Speichergrenzen, denn 220.000 Datensätze werden problemlos verarbeitet.
Seht ihr eine Möglichkeit diese zu umgehen (z.b. weil ich schlechte Routinen benutze, zuviel Speicher belege (System.gc() an diversen Stelle brachte leider keinen Erfolg) oder mein Ansatz ansich schon falsch ist) oder muss ich eine Speichererweiterung beantragen?
Typen in Oracle:
TYPE TYPE_JAVA_RECORD IS OBEJCT (WERT1 NUMBER, WERT2 NUMBER, ... , WERT26 NUMBER);
TYPE TPYE_JAVA_TABLE IS TABLE OF TYPE_JAVA_RECORD;
-> Ergo nichts anderes als ein 2d-Array.
Clob-Ausschnitt:
Java-Quelltext:
Noch ein paar Anmerkungen zum Code und den Fehlern.
Ich habe den Clob-Wert auf 2 verschiedene Arten versucht zu splitten. Beide Varianten funktionieren auch, solange weniger als ca. 220.000 Datensätze im Clob enthalten sind.
Sind es mehr bekomme ich bei
Variante 1 die Fehlermeldung: ORA-00932: nicht übereinstimmende Datentypen
Variante 2 die Fehlermeldung: java.lang.OutOfMemoryError 224217 (variiert)
Es liegt nicht an den Clob-Werten ansich (also keine Abweichungen der Sturktur ab einem bestimmten Datensatz). Es ist egal, welche 220.000 Datensätze ich auf dem Clob einlese, es treten keine Fehler auf. Nur sobald es weiter über 300.000 sind erhalte ich diese Fehlermeldungen.
Warum ich 2 unterschiedliche Fehlermeldungen erhalte (je nach Splitvariante) ist mir zwar nicht sonderlich klar, müsste aber auf die gleichen Speicherprobleme zurückzuführen sein.
Ich hoffe, mein Problem einigermaßen verständlich vermittelt zu haben und hoffe, ihr könnt mir vllt. ein paar Tipps gehen.
Vielen Dank schonmal an all diejenigen, die sich überhaupt die Mühe machen, sich den Code genauer anzuschauen!
Grüße
Jan
da ich mich immer mehr im Kreise drehe, dachte ich mir, frage ich mal die Experten
Folgendes Problem:
Aus einer Oracle-Datenbank bekomme ich einen Clob-Wert, welcher per Java in Token zerlegt werden soll und dann per Array als benutzerdefinierter Oracle-Datentyp zurückgegeben wird. Es werden 366.000 Datensätze übermittelt (kann variieren) und bei der Verarbeitung stosse ich wohl an Speichergrenzen, denn 220.000 Datensätze werden problemlos verarbeitet.
Seht ihr eine Möglichkeit diese zu umgehen (z.b. weil ich schlechte Routinen benutze, zuviel Speicher belege (System.gc() an diversen Stelle brachte leider keinen Erfolg) oder mein Ansatz ansich schon falsch ist) oder muss ich eine Speichererweiterung beantragen?
Typen in Oracle:
TYPE TYPE_JAVA_RECORD IS OBEJCT (WERT1 NUMBER, WERT2 NUMBER, ... , WERT26 NUMBER);
TYPE TPYE_JAVA_TABLE IS TABLE OF TYPE_JAVA_RECORD;
-> Ergo nichts anderes als ein 2d-Array.
Clob-Ausschnitt:
- 1;2923;21.27;20.27;22.82;17.85;6.80;2.46;3.72;3.49;9.99;8.62;20.78;140.81;110.36;104.73;104.33;116.72;168.98;214.95;209.01;233.92;65.01;78.43;97.32;72.54
1;2924;77.62;77.12;73.24;62.89;59.96;72.26;70.48;148.78;162.29;162.09;186.74;170.70;163.76;181.41;156.67;177.87;185.72;199.78;209.02;173.86;152.53;128.53;105.41;74.79
Java-Quelltext:
Code:
JAVA SOURCE NAMED "Java_Clob_Split" AS
import java.sql.*;
import java.io.*;
import java.util.*;
import oracle.sql.*;
import oracle.jdbc.*;
public class Java_Clob_Split
{
public static String returnJavaTable_String(java.sql.Clob clob_werte, oracle.sql.ARRAY[] arrayout) throws java.sql.SQLException, IOException, java.lang.VirtualMachineError
{
int i=0; // Datensatzzaehler
try {
// DB-Connection mit Oracle-Server
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:default:connection");
// Descriptoren für das Mapping der Oracle-Typen
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("TYPE_JAVA_TABLE", conn);
StructDescriptor struktDescriptor = StructDescriptor.createDescriptor("TYPE_JAVA_RECORD", conn);
int i_lines = 0; // Anzahl aller Datensaetze (Lines) im Clob
// Durchlauf aller Datensaetze im Clob um die gesammte Datensatzanzahl zu ermitteln (dient der Festlegung
// der Array Grenzen)
if (clob_werte !=null) {
Reader is = clob_werte.getCharacterStream();
LineNumberReader lr = new LineNumberReader(is);
String s = lr.readLine();
while(s!=null) {
i_lines++; // Zaehlen der Datensaetze
s=lr.readLine(); // Lesen der naechsten Zeile im Clob
}
}
STRUCT[] datensaetze = new STRUCT[i_lines]; // Speichert alle Datensaetze im Format TYPE_JAVA_TABLE
int j=0;
Object[] werte = new Object[26]; // Enthaelt die Werte 1-26 (fuer den Type TYPE_JAVA_RECORD)
// Auslesen des Clob-Wertes
if (clob_werte !=null){
Reader is = clob_werte.getCharacterStream();
BufferedReader br = new BufferedReader(is);
// ##### Split-Variante 1 (Stream-Tokenizer) #####
StreamTokenizer sToken = new StreamTokenizer(br);
while (sToken.nextToken() != StreamTokenizer.TT_EOF) {
// Falls es sich um einen nummerischen Wert handelt -> uebernehmen und ins Array schreiben
if (sToken.nextToken() == StreamTokenizer.TT_NUMBER){
werte[j] = new Float(sToken.nval); // Wert 1-26 mit Token fuellen
j++ ; // nächster der 26 Werte
// falls Wert > 25 wieder Wert 0 des Folgendatensatzes fuellen
if (j > 25) {
// neuen Datensatz im Array anlegen (TYPE_JAVA_TABLE)
datensaetze[i] = new STRUCT(struktDescriptor, conn, werte);
j = 0;
i++;
}
}
}
}
// ##### Ende Variante 1 ##############
// ############ Split-Variante 2 (String-Tolenizer #########
// String s = br.readLine();
// while(s!=null){
// StringTokenizer st = new StringTokenizer(s, ";"); // Trenne den String durch das Trennzeichen ;
// while (st.hasMoreTokens()) {
// werte[j] = new Float(st.nextToken()); // Wert 1-26 mit Token fuellen
// j++;
// if (j > 25) {
// datensaetze[i] = new STRUCT(struktDescriptor, conn, werte);
// j = 0;
// i++;
// }
// }
// s=br.readLine();
// }
// }
// #### Ende Variante 2 ######
// Rueckgabe-Array an die PL/SQL Funktioon
arrayout[0] = new ARRAY(descriptor, conn, datensaetze);
return "Alles ok";
}
catch(OutOfMemoryError ee) {
return ("Fehler: "+ee + " " +i);
}
}
}
Noch ein paar Anmerkungen zum Code und den Fehlern.
Ich habe den Clob-Wert auf 2 verschiedene Arten versucht zu splitten. Beide Varianten funktionieren auch, solange weniger als ca. 220.000 Datensätze im Clob enthalten sind.
Sind es mehr bekomme ich bei
Variante 1 die Fehlermeldung: ORA-00932: nicht übereinstimmende Datentypen
Variante 2 die Fehlermeldung: java.lang.OutOfMemoryError 224217 (variiert)
Es liegt nicht an den Clob-Werten ansich (also keine Abweichungen der Sturktur ab einem bestimmten Datensatz). Es ist egal, welche 220.000 Datensätze ich auf dem Clob einlese, es treten keine Fehler auf. Nur sobald es weiter über 300.000 sind erhalte ich diese Fehlermeldungen.
Warum ich 2 unterschiedliche Fehlermeldungen erhalte (je nach Splitvariante) ist mir zwar nicht sonderlich klar, müsste aber auf die gleichen Speicherprobleme zurückzuführen sein.
Ich hoffe, mein Problem einigermaßen verständlich vermittelt zu haben und hoffe, ihr könnt mir vllt. ein paar Tipps gehen.
Vielen Dank schonmal an all diejenigen, die sich überhaupt die Mühe machen, sich den Code genauer anzuschauen!
Grüße
Jan