große anzahl an inserts bei oracle db unperformant

Status
Nicht offen für weitere Antworten.

rambozola

Bekanntes Mitglied
hi leute,

ich hab ne datei die umfasst rund 61.000 zeilen.

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?

gibts da ne andere/bessere möglichkeit?

ich benutze jdk 5 und oracle 9.

vielen dank für eure antwort!
 

Bleiglanz

Gesperrter Benutzer
a) mit einer stored Procedure

b) 135 Stunden? schaffst du wirklich nur einen Insert pro Sekunde??

c) viele Indexe auf den betroffenen Tabellen? Constraints?

d) verwendest du prepared Statements?

e) du baust doch hoffentlich die Insert-Strings nicht mit + zusammen?
 

rambozola

Bekanntes Mitglied
zunächst einmal danke@Bleiglanz

zu a) was ist eine stored procedure

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(); }
	}

Was meinst du/ihr dazu? :?
 

rambozola

Bekanntes Mitglied
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.
 

rambozola

Bekanntes Mitglied
ok stevg wie gestalte ich das ganze performanter wenn nicht mit +?

muss ich da ein char[] oder ähnliches machen oder gibts gar ne Stringmethode die ich nicht kenne?
 
S

stev.glasow

Gast
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 :?
 

DP

Top Contributor
StringBuffer s = new StringBuffer("insert into REDE values(");
s.append(nrDerRede);
s.append(",");
s.append(satzNr);
.
.
.
.
dann ...execute(s.toString);
 

rambozola

Bekanntes Mitglied
@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.
 
S

stev.glasow

Gast
hab noch mal was editiert(siehe oben), ersters und letzters würde ich auf jeden fall nochmal bedenken, das letzte auch bei einer 8 MB Datei.
 

rambozola

Bekanntes Mitglied
ok stevg: wie gehts besser?

da ich bisher eher miniprogramme geschrieben habe hatte ich noch nie das problem mit großen zeichenmengen.
 
S

stev.glasow

Gast
gute Frage, weiß ich jetzt auch nicht ausm stehgreif.
Würde jetzt nen Scanner mit "<" als Delimiter auf dem FileinputStream laufen lassen.
 

bronks

Top Contributor
rambozola hat gesagt.:
@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.
 

Bleiglanz

Gesperrter Benutzer
Code:
redeTexteEinlesen() {
ist hoffnungslos inperformant

die whileschleife und darin dann ein teilstück aus einem String löschen mit delete?

ist das xml?
 
G

Guest

Gast
@bronks Ob man den String mit + oder - oder sonstwas zusammenbastelt ist eigentlich total egal, denn warten muß man immer auf die DB.

Einspruch!

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)

LG Robert
 

rambozola

Bekanntes Mitglied
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.

das ist io.

thanks nochmal.
thorsten
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
R Große Datensätze, kleine Rechte Datenbankprogrammierung 8
Joew0815 Datenmerge große Tabelle Datenbankprogrammierung 16
E MySQL Große Datenmengen reibungslos speichern für Gameserver Datenbankprogrammierung 6
T 3 GB Große CSV Datei einlesen und in SQL-DB schreiben Datenbankprogrammierung 12
L Große Datenbanken - Designproblem Datenbankprogrammierung 3
P Embedded Database und große Datenmengen Datenbankprogrammierung 23
A Große Datenmengen mit JPA 2.x verarbeiten Datenbankprogrammierung 13
F Große Datei in MySQL importieren Datenbankprogrammierung 10
A Große Objekte mit JPA und Hibernate Datenbankprogrammierung 3
S Zugriff auf eine große Datenmenge von MS Access per JDBC Datenbankprogrammierung 11
F JAVA und große Datenabfragen Datenbankprogrammierung 7
M Problem: Große Datei in MySQL DB importieren. Datenbankprogrammierung 12
R hsqldb: performance, große tabellen und so Datenbankprogrammierung 10
T Große Datenmenge bei DB- Abfrage Datenbankprogrammierung 5
ruutaiokwu Duplikate auf bestimmte Anzahl begrenzen Datenbankprogrammierung 8
C PostgreSQL Anzahl der Spalten ermitteln Datenbankprogrammierung 2
A Maximale Anzahl offener Cursor überschritten Datenbankprogrammierung 5
OnDemand SQL Query Anzahl der Werte Datenbankprogrammierung 8
Kandum MySQL Anzahl gefundener Datensätze bleibt gleich, auch wenn mehr existieren und ausgegeben werden Datenbankprogrammierung 3
S Anzahl Datensätze in db4o Datenbankprogrammierung 2
N Prepared Statement mit unbekannter Anzahl von Where-Clauses Datenbankprogrammierung 30
B Die Anzahl der Datensaetze einer Datenbank anzeigen Datenbankprogrammierung 2
Guybrush Threepwood H2: Anzahl an Usern begrenzen Datenbankprogrammierung 2
I MySQL - Anzahl Tabellen heraus finden Datenbankprogrammierung 6
A Maximale Anzahl offener Cursor überschritten Datenbankprogrammierung 4
I Anzahl unterschiedlicher Datensätze ausgeben Datenbankprogrammierung 2
D Anzahl der Elemente im ResultSet ermitteln Datenbankprogrammierung 8
J Maximale Anzahl von char in SQL Datenbankprogrammierung 11
E Maximale Anzahl offener Cursor Datenbankprogrammierung 9
W Anzahl der Spalten eines ResultSets bestimmen Datenbankprogrammierung 5
A Maximale Anzahl offener Cursor erreicht Datenbankprogrammierung 3
Z Zeilen-Anzahl abfragen bei Datenbank Datenbankprogrammierung 4
G Anzahl der Datensaetze abfragen Datenbankprogrammierung 11
S Anzahl geänderte Records Datenbankprogrammierung 2
V Anzahl der Datensätze abfragen Datenbankprogrammierung 9
B PreparedStatement - anzahl ParameterValues Datenbankprogrammierung 6
M Anzahl der Tabellen herausfinden Datenbankprogrammierung 6
M begrenzte anzahl von resultsets pro connection?? Datenbankprogrammierung 6
D Anzahl der zurückgelieferten Datensätze Datenbankprogrammierung 2
L Oracle SQL Inserts via Client vs SQL Datei via ScriptRunner Datenbankprogrammierung 6
G HSQLDB Inserts/Updates sind nach Neustart der Anwendung Datenbankprogrammierung 1
J Mehrere Inserts bei Fehlschlag abbrechen Datenbankprogrammierung 2
D Frage zu INSERTS über mehrere Datenbanktabellen Datenbankprogrammierung 3
T MySQL PreparedStatement mit INSERTs langsam, Batch-Statement auch Datenbankprogrammierung 4
M SQL inserts bringen Router zum Absturz Datenbankprogrammierung 8
H Inserts in 2 Tabellen 1:n Datenbankprogrammierung 6
alexpetri Problem mit jdbc MS Access / nach 670 inserts ist schluss. Datenbankprogrammierung 4
M executeBatch() - Inserts trotz Fehler weitermachen Datenbankprogrammierung 5

Ähnliche Java Themen


Oben