Arbeiten mit sehr großen CSV Dateien

nrg

Top Contributor
Hallo Zusammen,

ich weiß, ähnliche Themen gab es hier in letzter Zeit öfters aber ich mache ein neues auf, weil ich mein Problem in den anderen nicht direkt wiederfinden konnte ;).

Ich lese große CSV-Dateien ein (500.000 Datensätze). Jeder Datensatz ist ein Element einer
Code:
List<String>
. Diese splitte ich dann in eine
Code:
List<String[]>
, d.h. ich hätte bereits rund 1Mio Objekte. Warum ich das so machen muss, hat den Hintergrund, weil die komplette Datei zu jedem Datensatz, der verarbeitet wird, zugänglich sein muss. Es kann sein, dass bei Datensatz 400000 auf den ersten zugegriffen wird. Ausserdem erfolgt bei jedem Datensatz eine Prüfung. Liefert diese
Code:
false
, wird der aktuelle Datensatz einer Errorliste hinzugefügt. D.h. ich brauch im Grunde beide Listen zu jeder Zeit.
Dazu kommt am Ende natürlich noch der Output.

Einzige Option, die ich hier sehe ist, die
Code:
List<String>
mit einem Iterator zu durchlaufen und wenn ein Datensatz erfolgreich bearbeitet wurde, diesen zu entfernen. Dadruch würde die HeapSize schonmal im Laufe des Prozess wenigstens stagnieren (1 Datensatz Input = 1 Datensatz Output bzw. 1 Errordatensatz) - in manchen Fällen würde die HeapSize auch abnehmen.

Nun zur Frage: Was bleibt mir anderes übrig, als die HeapSize massiv hochzusetzen?
Ändere ich den Ablauf (direkter Split beim Lesen) verzichte ich auf einige Funktionen des Programms, auf die leider kein Verzicht ist. Die Möglichkeit beim Lesen direkt zu Splitten und die Bedingung zu prüfen (habe mir das schon in Form eines Interfaces
Code:
EntityFilter
mit
Code:
accept(String[] entity)
überlegt) funktioniert leider auch nicht ganz, weil zum Zeitpunkt der Prüfung die komplette
Code:
List<String[]>
zur Verfügung stehen muss.

Danke schonmal
Grüße
Andi
 

XHelp

Top Contributor
Was soll denn anschließend passieren? Du kannst z.B. eine Datenbank einsetzen um nicht alle Einträge im Speicher zu halten, sondern nur die, die du im Moment benötigst.
 

XHelp

Top Contributor

Naja, du wirst das ganze ja nicht machen, weil es einfach nur Spass macht CVS Dateien einzulesen. Die Verarbeitung passiert doch bestimmt aus einem Grund. Wenn du z.B. mit den Daten im Programm arbeiten muss und damit du die Daten da hast, musst du die jedes mal beim Programmstart einlesen, dann wäre es wirklich sinnvoll eine eingebettete Datenbank zu nutzen.
 

nrg

Top Contributor
Naja da handelt es sich im Grunde um einen Konverter. Auf der einen Seite kommt eine CSV rein, wird verarbeitet und ein Output erzeugt (ggf. + Erroroutput). Der Input variiert immer und somit komme ich auch nicht daran vorbei das auch immer wieder neu einzulesen. Wenn ich die Möglichkeit hätte, direkt von Datenbanken zu lesen, würde ich das tun (ist im Converter implementiert nur leider lässt das nicht immer das Kundensystem zu).

Mit Standalone meine ich, dass das Programm ganz ohne jegliche Datenanbindung o.ä. funktioniert. Es soll eben möglichst einfach gestrickt sein. Wenn ich die Möglichkeit hätte performant die Daten auf der Platte zwischenzuspeichern und darauf zuzugreifen (sei es über SQL oder Hash), wäre das vielleicht noch eine Option. Jetzt kommt sogar noch das Reverenzlesen aus anderen Dateien dazu. Die Funktionalität ist geschaffen nur wird der Speicher ja jetzt schon knapp. Dafür darf ich dann nochmal eine Datei in eine HashMap laden, um performant darauf zugreifen zu können (auch hier wär mir eine DB lieber - nur leider lässt das der Kunde nicht zu)

Ich habe nur oft gelesen, dass ein heraufsetzen der HeapSize meinst konzeptionelle Probleme voraussetzt und man das i.d.R. nicht braucht. Für meine Einschätzung gibt es aber keine Ressourcen im Prozess auf die ich Verzichten könnte.
 

XHelp

Top Contributor
Ja, aber du musst ja jetzt nicht jedes mal einen MySQL Server einrichtigen... kannst doch eine eingebettete DB nehmen, der Kunde sieht dann nix von.
 

nrg

Top Contributor
Genau sowas könnte ich mir vorstellen.

Also ich les die Datei ein und speicher die einfach in einer Datenbank zwischen - die liegt dann im classpath einfach in Form einer Kontainerdatei. Nun kann ich auf diesen Kontainer Querys ausführen. Das wäre eine denkbare Alternative für mich :).

Kann HyperSQL sowas? Ein Kollege hat mir grad Perst vorgeschlagen (edit: empfohlen nicht wirklich, weil er selbst damit noch nicht viele Erfahrungen gesammelt hat). Hat jemand Erfahrungen damit?
 
M

maki

Gast
HyperSQl == HSQLDB == HSQL

Wurde auch schon vorgeschlagen... H2 und Derby/JavaDB können das auch ;)
 

nrg

Top Contributor
HyperSQl == HSQLDB == HSQL

ja. war eben auf HoaX Post bezogen :)


H2 und Derby/JavaDB können das auch ;)

werd ich mir mal anschauen edit: auch persönliche Vorlieben oder Empfehlungen nehme ich gerne mit. Also wenn jemand vielleicht bereits aus Erfahrung sagen kann, dass sich das eine mehr das andere weniger dafür eignet. Soll wirklich lightweight sein. Also am liebsten eine .jar in ClassPath und fertig ;)


Jetzt noch eine Frage: wäre Serialisierung vielleicht auch eine Alternative oder muss ich da vielleicht schon wieder Performance einbüßen?

Ansonsten Danke allen für die Hilfe :)
 
Zuletzt bearbeitet:

nrg

Top Contributor
Naja dadurch könnte ich ja den Heap zur Laufzeit entlasten und ggf. Objekte holen, wenn ich es benötige. Aber glaube ehrlich gesagt nicht, dass der Lese- und Schreibaufwand mit der Performance einer embedded db mithalten kann. war nur eine Überlegung ;)
 

LoR

Bekanntes Mitglied
Wenn es möglich ist, dann stell die Datei mal zum Download bereit. Eventuell findet es sich dann eine bessere Alternative als eine DB. Datenbanken sind meist zuviel Overhead und nur bei wirklich sehr großen Datenmengen erste Wahl.
 
B

bone2

Gast
kannst du nicht direkt 1 zeile lesen, bearbeiten/infos rausziehen , schreiben usw?
wenn du so auf element 400k zugreifen musst, les doch in dem moment einfach zeile 400k ein. gibt es einen grund warum du alle 500k elemente im speicher haben musst?
 

nrg

Top Contributor
der Converter ist gleichzeitig eine Plattform für mehrere Textschnittstellen. Um alle abzudenken, habe ich mir überlegt, die Dateien einfach aufzubereiten und die Daten einer ScriptEngine zu übergeben. Jetzt kann man zum einem auf den aktuellen Datensatz in Form eines Arrays zugreifen und zum anderen auf beliebige Felder der kompletten Datei. Zusätzlich kann ich natürlich ganz einfach Utility-Funktionen hinzufügen oder Datenbankzugriffe ermöglichen)

Code:
feld1 = field[10] #das erste feld der ausgabezeile = das 11 feld der aktuellen eingabezeile
feld2 = index.get(row+2, 10) #das zweite feld der ausgabezeile = das 11 feld der aktuellen eingabezeile+2
feld3 = util.getTimeStamp("yyyy") #aktuelles Jahr
.....

Es werden auch nicht alle Zeilen verarbeitet. eine Satzbeschreibung sieht z.B. so aus

Code:
s;002;bla;gesamtbetrag;kst
g;betrag1;ktr
g;betrag2;ktr
g;betrag3;ktr
g;betrag4;ktr

hier interessieren mich z.b. nur alle Sätze, die mit S anfangen. d.h. ich habe in meinen Properties z.b. eine accept_condition definiert.
Code:
field[0] == "s"
; wenn diese
Code:
true
liefert, wird der Datensatz überhaupt bearbeitet. Dann wird die parse_condition abgeprüft (z.b:
Code:
field.length == 5
, weil die Qualifier auch gern mal wie Kraut und Rüben sind und somit manchmal quatsch raus kommt). Wenn diese nicht erfüllt ist, wird der aktuelle Datensatz bis zum nächsten Datensatz, der die accept_condition erfüllt in eine Errorliste aufgenommen (also hier Datensatz 1-5, 6 wäre ja dann wieder ein s-satz).
Die g-Sätze kann ich natürlich nicht ignorieren, weil es gut sein kann, dass man mit
Code:
index.get(row+2, 10)
darauf zugreift.

So ist z.b. die Logik. Sind wirklich teilweiße sehr exotische und ständig wechselnde Wünsche der Kunden, wodurch ich mit der Dynamik einer propertiesgesteuerten ScriptEngine am besten dran bin.

Das funktioniert alles ja auch wunderbar nur jetzt kommt der nächste mit 500.000 Datensätze.
Option a: HeapSize massiv erhöhen
Option b: Suche ich grad :)

ich schau mir grad HyperSQL und H2 an. Mal sehen ob ich das auf den Datensatzprozess der CSV-Dateien übertragen kann. Gerade bei H2 auch gesehn, dass es dort CSVREAD statements gibt. Somit könnte ich vielleicht das Referenzlesen aus anderen Dateien outsourcen (was derzeit in einer HashMap für einen schnellen Zugriff gespeichert wird - was natürlich auch wieder massig HeapSize schluckt).

Ist etwas viel aus einmal aber vielleicht hat ja jemand noch einen Tipp. Ich werde es auf jedenfall mal mit einer embedded DB probieren. Im Zweifelsfall muss halt die HeapSize hoch :D
 

nrg

Top Contributor
das ganze als array/Hashmap mit SoftReferences umsetzen, die bei bedarf aus der Datei regeneriert werden können.

bei dem Speicherbedarf würde der GC mir alle SoftReferenzen nach 30% Process kicken. Da kann ich dann soviel aus der Datei regenerien, dass das imho in keinem Verhältnis mehr steht.

werd mich wohl mal an embedded db rantasten. am liebsten wäre mir eine möglichkeit die CSV einfach schnell in Tabellenform abzulegen und dann mit get(row, column) darauf zugreifen zu können (edit: wobei das mit normalen selects und einer id spalte ja ohne probleme projizierbar ist). eignet sich da vielleicht eine library besonders? ansonsten werd ich wohl mal mit h2 oder hsql anfangen.
 
Zuletzt bearbeitet:

nrg

Top Contributor
hab mich jetzt etwas in h2 reingelesen. hört sich genau nach dem an, was ich brauche. eventuell auch in verbindung mit hibernate. vielen dank für die hilfe
 

HoaX

Top Contributor
Solange es nur um solch triviales Datengeschubse geht würde ich Hibernate da raus lassen. Wenn man keine Übung damit hat, kann das schnell zur Performacebremse werden.
 

nrg

Top Contributor
eine Frage hätte ich noch. Wie bekomme ich ein java.sql.Array Array (Java Platform SE 6) in ein Object[] ? Ich hab dort nur eine Methode Object getArray(), hätte aber eher eine Object[] getArray() erwartet :). Geschrieben wurd das Array mit einem PreparedStatement. Wenn ich mir das Object, das das ResultSet liefert im Debugger ankucke, sieht das schon sehr nach einen Array aus. Muss ich jetzt ersthaft davon wieder ein ResultSet holen und da drüberiterieren?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
O Lernen im Team zu arbeiten - Projekte zusammen umsetzen Allgemeine Java-Themen 23
D Arbeiten mit einem Bitarray Allgemeine Java-Themen 13
D Mit Generics arbeiten - Übungsaufgabe Allgemeine Java-Themen 3
E mit extrem langen Zahlen (als Zeichneketten) arbeiten Allgemeine Java-Themen 4
F Input/Output Arbeiten mit dem JFileChooser Allgemeine Java-Themen 4
antonbracke Aus Jar eine Class laden und damit arbeiten! Allgemeine Java-Themen 5
P [Thread] Scheint nicht Sequenziell zu Arbeiten Allgemeine Java-Themen 9
P Eclipse Gemeinsam mit NetBeans an einem Projekt arbeiten? Allgemeine Java-Themen 3
G Wie kann man sehen, welche Applikationen mit java arbeiten? Allgemeine Java-Themen 17
S Schnelles arbeiten mit großen CSV Dateien Allgemeine Java-Themen 4
J Mit mehrdimensionalen Integer-Arrays arbeiten Allgemeine Java-Themen 17
J Arbeiten mit Punkten in einem JPanel Allgemeine Java-Themen 3
V Java-Programm nur "mit halber Kraft" arbeiten lass Allgemeine Java-Themen 11
J Methode nur max 1sec arbeiten lassen Allgemeine Java-Themen 2
C Strings zu groß um damit zu arbeiten Allgemeine Java-Themen 31
M Wie bekomme ich Threadsdazu parallel zu arbeiten? Allgemeine Java-Themen 13
B Arbeiten mit Dateien Allgemeine Java-Themen 2
D Fehlerhafte Thread Verwendung beim arbeiten mit Sockets Allgemeine Java-Themen 6
W Mit Date-Objekten arbeiten Allgemeine Java-Themen 10
M Mit Textdateien arbeiten Allgemeine Java-Themen 5
B Sehr großen Graph mit Verbindungen bauen und minimieren? Allgemeine Java-Themen 35
javamax2000 Sehr sonderbares Verhalten Allgemeine Java-Themen 6
B Welcher Datentyp für sehr große Zahlenbereiche? Allgemeine Java-Themen 1
P Rechnen mit sehr kleinen Zahlen Allgemeine Java-Themen 5
R JDK installieren OpenJDK-Aufruf sehr langsam Allgemeine Java-Themen 4
Thallius String erzeugen sehr langsam Allgemeine Java-Themen 16
D Verwaltung von sehr vielen Objekten Allgemeine Java-Themen 12
S JNLP startet seit 1.8.0_31 sehr langsam + Windows-Systemverzeichnis Allgemeine Java-Themen 3
Creylon Java verursacht sehr starkes ruckeln Allgemeine Java-Themen 5
N Bin to Dez und umgekehrt mit sehr großen Zahlen Allgemeine Java-Themen 2
T Gleiche Operation dauert teilweise sehr lange Allgemeine Java-Themen 12
M Externe Jar sehr langsam Allgemeine Java-Themen 23
M JUnit & Multithreading - sehr seltener Fehler Allgemeine Java-Themen 3
H Sehr viele Threads effizient Verwalten Allgemeine Java-Themen 13
J Laden von JAR Files geht ohne ADMIN Rechte sehr langsam Allgemeine Java-Themen 6
H Kopieren sehr langsam Allgemeine Java-Themen 5
B Cipher.getInstance Aufruf sehr langsam Allgemeine Java-Themen 2
K replaceAll bei sehr großen String Allgemeine Java-Themen 3
B Eingabemaske Komponenten aktivieren, funktionert nicht (sehr kurios) Allgemeine Java-Themen 2
hdi Heap Sapce Error bei sehr großem String Allgemeine Java-Themen 5
G RXTX library braucht sehr lange zum laden. Ist das normal? Allgemeine Java-Themen 8
L Java 1.5 - Anwendung unter 1.6 JRE sehr langsam geworden Allgemeine Java-Themen 8
O Speicherverbrauch von Java / VM sehr hoch? Allgemeine Java-Themen 27
M Rechnen mit sehr kleinen Zahlen Allgemeine Java-Themen 8
G Lesen von sehr großen dateien Allgemeine Java-Themen 8
M String zusammensetzen->sehr langsam Allgemeine Java-Themen 3
G Sehr sehr merkwürdige Ereignisse mit Fibonacci Programm Allgemeine Java-Themen 6
G Sehr gutes Java-Framework(Gui-Builder) auf XML-Basis gesucht Allgemeine Java-Themen 21
E String.replace für (sehr) großen Text Allgemeine Java-Themen 9
T [SVNKit] Commit sehr langsam. Allgemeine Java-Themen 7
G Arraylist statt List - Sehr schlimm? Allgemeine Java-Themen 8
F JAVA Applikationen starten sehr langsam Allgemeine Java-Themen 14
D Datei öffnung sehr langsam Allgemeine Java-Themen 17
G Neue Warenwirtschaft aber sehr langsam! Allgemeine Java-Themen 3
H Entpacken sehr langsam Allgemeine Java-Themen 10
Bleiglanz Benchmarks sind sehr schwierig Allgemeine Java-Themen 2
T Modulo-Operator versagt bei zu großen Zahlen? Allgemeine Java-Themen 14
H Gibt es einen großen Unterschied zwischen Java 6 und Java 7? Allgemeine Java-Themen 3
R Panel mit 8 gleich großen "fenstern" Allgemeine Java-Themen 11
M Eclipse Stackoverflow beim Einlesen von großen Bilder in kd Baum Allgemeine Java-Themen 15
H2SO3- großen double in string mit e umwandeln Allgemeine Java-Themen 4
kb22 CMS mit großen Dateien (heap problem) Allgemeine Java-Themen 3
H2SO3- speichern von Daten in seeeeeehr großen Tabellen (nicht DB) Allgemeine Java-Themen 8
G Bringt es etwas System.gc() nach großen Aufgaben aufzurufen? Allgemeine Java-Themen 2
T Suche den großen Calendar Thread ! Allgemeine Java-Themen 2
U Kompilieren einer großen Datei if-else = StackOverflowError Allgemeine Java-Themen 4
S Datenbank Abfragen mit großen Datenmengen Allgemeine Java-Themen 22
M String#equals(), Probleme mit großen Strings? Allgemeine Java-Themen 4
F Mehrere Bilder zu einem Großen zusammenkleben Allgemeine Java-Themen 3
R Was nehmen für Flußdiagramme und Druck von großen Grafiken Allgemeine Java-Themen 4
W JTextArea beschleunigen bei großen Texten Allgemeine Java-Themen 4
flashfactor Problem mit mehren großen Dateien Allgemeine Java-Themen 3

Ähnliche Java Themen


Oben