Ich habe eine große CSV-Datei mit etwa 5,2 Millionen Zeilen. Ich möchte diese Datei analysieren und die Daten in eine Datenbank einfügen. Ich benutze Apache Kamel dafür.GC-Probleme beim Einfügen einer großen CSV-Datei mit Apache Camel
Der Weg ist ziemlich einfach (für dieses Beispiel vereinfacht)
from("file:work/customer/").id("customerDataRoute")
.split(body().tokenize("\n")).streaming()
.parallelProcessing()
.unmarshal(bindyCustomer)
.split(body())
.process(new CustomerProcessor())
.to("sql:INSERT INTO CUSTOMER_DATA(`FIELD1`,`FIELD2`) VALUES(#,#)");
bindyCustomer ist ein BindyCsvDataFormat für die CSV-Datei und CustomerProcessor ist ein Prozessor, der die Daten des Bindy Customer-Objekt als eine Reihe von Objekten zurückgibt für die SQL-Einfügung. Das eigentliche Objekt hat 39 Felder (oben vereinfacht).
Dies funktioniert alles in Ordnung für die ersten 800.000 bis 1.000.000 Linien, aber dann kommt es zum Stillstand.
Ich habe die Camel-Instanz mit JVisualVM und dem Visual GC-Plugin überwacht und sehe, dass die alte Generation voll wird und wenn sie das Maximum erreicht, kommt das ganze System zum Stillstand, aber es stürzt nicht ab. An diesem Punkt ist die alte Generation voll, der Eden-Raum ist fast voll und beide Survivor-Räume sind leer (da sie nichts an die alte Generation rühren können, denke ich).
Was ist hier falsch? Das sieht für mich wie ein Speicherleck in der Camel SQL Komponente aus. Die Daten werden hauptsächlich in ConcurrentHashMap-Objekten gespeichert.
Wenn ich die SQL-Komponente herausnehme, füllt sich die alte Generation kaum.
Ich benutze Camel 2.15.1 Wird versuchen, 2.17.1 zu verwenden, um zu sehen, ob das das Problem behebt.
Update: Ich habe Camel 2.17.1 (das gleiche Problem) versucht und ich habe versucht, die tun die Einsätze in Java mit java.sql.Statement.executeUPdate einfügen. Mit dieser Option konnte ich ungefähr 2.6 M Zeilen einfügen, aber dann hörte es auch auf. Das Lustige ist, dass ich keinen Speicherfehler bekomme. Es kommt einfach zum Stillstand.
Danke für den Tipp. Ich habe es versucht, aber es hat das Problem nicht gelöst. Der .unmarchal (bindyCustomer) gibt ein Array mit nur einem Element zurück, so dass das Streaming in diesem Fall sowieso keinen großen Unterschied gemacht hat. Kannst du an etwas anderes denken, das falsch sein könnte? Ich werde versuchen, die Einfügung in Java zu machen, um zu sehen, ob das das Problem behebt. – Ben
Hmm Ich habe ein paar grobe Vermutungen. Wären Sie in der Lage, ID-Tags zu Ihrer Route hinzuzufügen und dann Ihre JConsole zu öffnen, um zu bestätigen, wo alle Threads "hängen" sind? –
Die Route bereits als ID (customerDataRoute) oder beziehen Sie sich auf etwas anderes? – Ben