Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
große anzahl an inserts bei oracle db unperformant
diese muss ich im java-programm auslesen und jede zeile noch zerlegen und stringoperationen durchführen.
die ergebnisse soll ich dann noch in 3 oracle tabellen einfügen.
sagen wir mal für jede zeile hab ich im mittel 15 operationen...dann hab ich 640.500 inserts zu bewerkstelligen.
hatte das ganze mit executeQuery im jdbc (thin) propiert....hatte dann ausgerechnet das ich rund 135 h bräuchte bis alles eingetragen ist :lol:
dann hab ich gelesen das man noch ne batchverarbeitung machen kann (--> executeBatch() )...hab das implementiert aber mein rechner ist immer noch zu langsam und wird nich fertig.
habt ihr ne idee wie ich solch große datenmengen viel performanter in meiner oracle db unterbringen kann?
c) indexe dürfte ich nicht verwenden...die 4 tabellen sind nur durch diverse PS-FS-Beziehungen miteinander verknüpft
d) bei meiner batchverarbeitung gehe ich folgender maßen vor.
s ist ein statement. ich adde die inserts mit s.addBatch(updateString); und führe dann s.executeBatch();
und s.clearBatch(); aus bevor ich den batch für eine andere tabelle wieder neu befülle.
e) nee, ausser das + um die notwendigen variablen zu nehmen baue ich die strings nicht mit + zusammen
hier mal ein bisserl code von mir damit du das ganze siehst
Code:
private static void redeTexteEinlesen() {
String gesamtInhaltDerDatei = allesAusDateiAuslesen();
ora.batchInitialisieren();
//try{
//in tokens = sätze zerlegen
//StringTokenizer dateiTokens = new StringTokenizer(gesamtInhaltDerDatei,".");
String anfrageString = "";
while(gesamtInhaltDerDatei.indexOf('<')!= -1){
//tag auslesen
int tagAnfang = gesamtInhaltDerDatei.indexOf('<');
int tagEnde = gesamtInhaltDerDatei.indexOf('>');
String taginhalt = gesamtInhaltDerDatei.substring(tagAnfang+1, tagEnde);
//System.out.println("taginhalt= "+taginhalt);
//tag aus satz löschen
StringBuffer sb = new StringBuffer(gesamtInhaltDerDatei);
gesamtInhaltDerDatei = sb.delete(0, tagEnde+1).toString();
//System.out.println("gesamtInhaltDerDatei ohne tag = "+gesamtInhaltDerDatei);
String satzEinerRede = null;
//wenn ende der datei nicht erreicht
if(gesamtInhaltDerDatei.indexOf('<')!= -1){
// satz = von stelle 0 bis index of '<'
satzEinerRede = gesamtInhaltDerDatei.substring(0, gesamtInhaltDerDatei.indexOf('<'));
//System.out.println("satzEinerRede = "+satzEinerRede);
}
//dateiende erreicht
else{
satzEinerRede = gesamtInhaltDerDatei;
gesamtInhaltDerDatei = "";
}
//eingelesenen satz rauslöschen
sb = new StringBuffer(gesamtInhaltDerDatei);
tagAnfang = gesamtInhaltDerDatei.indexOf('<');
if(tagAnfang != -1){
gesamtInhaltDerDatei = sb.delete(0, tagAnfang).toString();
//System.out.println("gesamt ohne satz = "+gesamtInhaltDerDatei);
}
StringTokenizer tagStringTokenizer = new StringTokenizer(taginhalt,":");
String nrDerRede = tagStringTokenizer.nextToken();
//System.out.println("nrDerRede = "+nrDerRede);
String satzNr = tagStringTokenizer.nextToken();
//System.out.println("satzNr = "+satzNr);
String praesident = tagStringTokenizer.nextToken();
//System.out.println("praesident = "+praesident);
StringBuffer satz = new StringBuffer(satzEinerRede);
//tag aus satz rausschneiden
//satz.delete(0, tagEnde+1);
//System.out.println("satz vor hochkommabearbeiten= "+satz.toString());
//anstatt ' muss '' im satz stehen
satz = satzHochKommataBearbeiten(satz);
//System.out.println("satz nach hochkommabearbeiten= "+satz.toString());
//vectoren für spätere behandlung bei VOLLINDEX befüllen
nrDerRedeVector.addElement(nrDerRede);
nrDesSatzesVector.addElement(satzNr);
satzVector.addElement(satz);
anfrageString = " insert into REDE values("+nrDerRede+","+satzNr+","
+"'"+praesident+"','"+satz+"')";
System.out.println("anfrageString = "+anfrageString);
ora.batchFuellen(anfrageString);
}
//ora.sqlAnfrageAnDBSchicken(anfrageString);
ora.executeBatch();
//inDateiFuerSchnelleresInsertSchreiben(anfrageString);
//}
/*catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
Der angegebene Code betrifft nur eine von den 4 tabellen.bei den anderen ist das ganze noch komplizierte da die eingelesenen texte auf sonderzeichen überprüft u bearbeitet werden müssen und danach zerlegt werden.
ich poste dir auch mal meine sql-klasse
ora ist eine instanz meiner sql-klasse
Code:
.....
Statement s = null;
.....
public void batchInitialisieren() {
try {
conORACLE.setAutoCommit(false);
if (conORACLE != null) {
s = conORACLE.createStatement();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void batchFuellen(String updateString) {
try {
s.addBatch(updateString);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* batch wird übertragen und geleert -->clear
*
*/
public void executeBatch(){
try
{
s.executeBatch();
s.clearBatch();
}
catch ( BatchUpdateException e ) { e.printStackTrace();}
catch ( SQLException e ) {e.printStackTrace(); }
}
eine sache müsste ich noch ergänzen...ich committe die transaktion erst am ende meines programmes...soweit komme ich allerdings nicht, da vorher der java-heap-space nicht reicht u ich eine oom-exception bekomme.
die parameter -Xms und -Xmx habe ich bereits verwendet.
Versuch mal StringBuffer bzw. StringBuilder
[edit]
Noch was ganz böses: String gesamtInhaltDerDatei = allesAusDateiAuslesen();
Die Datei ist bestimmt recht groß, und mit der Zeile haust du die ganze Datei in den Arbeitsspeicherm kannst du das nicht evt. zeilenweise oder ähnliches einlesen ?
[edit]
Dass bei jedem Durchgang was vom gesamtInhaltDerDatei-String abgeschnitten und wieder in die Varibale gespeichert wird ist auch gar nicht gut.
sry, aber keine Wunder das dir das um die Ohren fliegt, ich weiß der Spruch hilft nicht viel aber deine Stringsachen musst doch nochmal überdenken :?
StringBuffer s = new StringBuffer("insert into REDE values(");
s.append(nrDerRede);
s.append(",");
s.append(satzNr);
.
.
.
.
dann ...execute(s.toString);
@stevg die datei ist 8 mb groß u ich denke ich muss sie komplett einlesen da ich sie ja in mehreren sequentiell aufeinanderfolgenden methoden (lt. aufgabenstellung) benötige.
an euch beide: jepp stringbuffer is ne gute idee ich propier das jetzt mal aus.
@stevg die datei ist 8 mb groß u ich denke ich muss sie komplett einlesen da ich sie ja in mehreren sequentiell aufeinanderfolgenden methoden (lt. aufgabenstellung) benötige ...
Ich habe mir auch mal eingebildet, daß man die Daten so in die DB reinbekommt, aber das kann man echt vergessen.
Ob man den String mit + oder - oder sonstwas zusammenbastelt ist eigentlich total egal, denn warten muß man immer auf die DB.
60000 Zeilen im Batch überfordern Java um einiges und auch wenn es nur 1000 Zeilen sind, dann wäre es wegen dem Verwaltungsaufwand deutlich langsamer, als einzelne Executes. Das ganze in einer Transaktion ist auch nicht ratsam, weil die DB nicht die Geduld aufbringen wird in einer Transaktion so lange zuzuhören und Dir die Transaktion kickt.
Eine 8 MB-Datei im Speicher zu halten und mehrere male durchzunudeln ist auch kein Spaß für die JVM und bringt keinen Performancevorteil.
Gestalte das Programm so, daß die Datei zeilenweise abgearbeitet wird und das Füllen der 4 Tabellen je Dateizeile in einer Transaktion und im Batch abgearbeitet wird. Wohl gemerkt: Je Zeile eine Transaktion und ein Batchaufruf. Bei den schnellsten Produktivsystemen, die ich kenne würde ich mit <400 Transkationen je Minute rechnen.
Zum Einspielen von Daten bieten die DBs bessere Werkzeuge, welche man auch verwenden sollte.
Aus meiner Sicht sollte unbedingt das INSERT ...VALUES(Daten)... durch ein PreparedStatement (=INSERT ... VALUES(?, ?) ersetzt werden.
1. spart man sich ein paar String(Buffer) Manipulationen ein (pro Transaktion, also x INSERT's)
2. muss die Datenbank den Befehl nur 1x interpretieren / bzw. hat einen kürzen String zu interpretieren (je nach DB)
3. hat eben diese Optimierung von 2., unschöne Nebenwirkungen bei INSERT's ohne Parameter (macht den Statement Cache zu - kann in's Gegenteil umschlagen)
vielen dank leute für eure hilfe...ich habs jetzt so hinbekommen mit der batchverarbeitung und auto-commit off (committet wird nur alle 1000 transaktionen) das ich ca 1000 transaktionen pro minute geschafft habe (mit hoher prio im taskmanager).
mein proggie war also mit den ca 61000 zeilen die mehrere inserts ergaben nach bissi über ner h fertig.