Frage

Ich habe eine Datei mit Größe 2GB, in der Schüleraufzeichnungen enthalten sind. Ich muss Schüler basierend auf bestimmten Attributen in jedem Datensatz finden und eine neue Datei mit Ergebnissen erstellen. Die Reihenfolge der gefilterten Schüler sollte wie in der Originaldatei sein. Was ist die effiziente und schnellste Art, dies mit Java IO -API und Threads ohne Speicherprobleme zu tun? Die Maxheap -Größe für JVM ist auf 512 MB eingestellt.

War es hilfreich?

Lösung

  1. 2 GB für eine Datei ist riesig, Sie sollten sich für eine DB entscheiden.
  2. Wenn Sie wirklich verwenden möchten Java I/O API, Dann probieren Sie das aus: Umgang mit großen Datendateien effizient mit Java und das: Tuning von Java I/O -Leistung

Andere Tipps

Welche Art von Datei? Textbasiert, wie CSV?

Der einfachste Weg wäre, so etwas wie Grep zu tun: Lesen Sie die Dateizeile nach Zeile, analysieren Sie die Zeile, überprüfen Sie Ihr Filterkriterium, geben Sie eine Ergebniszeile aus und gehen Sie dann zur nächsten Zeile, bis die Datei fertig ist. Dies ist sehr speichereffizient, da Sie nur die aktuelle Linie (oder einen Puffer etwas größer) gleichzeitig geladen sind. Ihr Prozess muss nur einmal die gesamte Datei durchlesen.

Ich glaube nicht, dass mehrere Themen viel helfen werden. Es würde die Dinge viel komplizierter machen, und da der Prozess ohnehin an die I/O -gebundenen Personen zu sein scheint, verbessert der Versuch, dieselbe Datei mit mehreren Threads zu lesen, wahrscheinlich keinen Durchsatz.

Wenn Sie feststellen, dass Sie dies oft tun müssen und jedes Mal die Datei durch die Datei zu durchlaufen, müssen Sie eine Art Index erstellen. Der einfachste Weg, dies zu tun, wäre, die Datei zuerst in einen DB (kann ein eingebettetes dB wie SQLite oder HSQL) importieren.

Ich würde dies nicht überkomplizieren, bis Sie feststellen, dass der bewegend einfache Weg nicht für das funktioniert, was Sie brauchen. Im Wesentlichen müssen Sie nur:

  • Öffnen Sie Eingabestream in 2 GB Datei, erinnern Sie sich an den Puffer (z. B. durch Wickeln mit BufferedInputStream)
  • Öffnen Sie den Ausgangsstream für gefilterte Dateien, die Sie erstellen werden
  • Lesen Sie den ersten Datensatz aus dem Eingabestream und sehen Sie sich das Attribut an, um zu entscheiden, ob Sie es "brauchen". Wenn Sie dies tun, schreiben Sie es in die Ausgabedatei
  • Wiederholen Sie dies für verbleibende Datensätze

Auf einem meiner Testsysteme mit extrem bescheidener Hardware, BufferedInputStream um einen DateiInputStream, lesen Sie etwa 500 MB in 25 Sekunden, dh wahrscheinlich unter 2 Minuten, um Ihre 2 GB -Datei zu verarbeiten, und die Standardpuffergröße ist im Grunde genommen so gut wie es (Siehe BufferedInputStream -Timings Ich habe weitere Details gemacht). Ich stelle mir vor, mit der Kunsthardware ist es durchaus möglich, dass die Zeit halbiert wird.

Egal, ob Sie sich viel Mühe machen müssen, um die 2/3 Minuten zu reduzieren oder nur für eine kleine Zeit zu warten, bis Sie darauf warten, dass Sie abhängig von Ihren Anforderungen treffen müssen. Ich denke, die Datenbankoption kauft Sie nicht viel, es sei denn, Sie müssen viele verschiedene Verarbeitungsläufe auf demselben Datensatz ausführen (und es gibt andere Lösungen dafür, die keine Datenbank automatisch bedeuten).

Ich denke, Sie sollten verwenden Speicher zugeordnet Dateien. Dies hilft Ihnen, die größere Datei einem kleineren Speicher zuzuordnen. Dies wirkt sich wie virtueller Speicher und was die Leistung betrifft, sind kartierte Dateien schneller als das Schreiben/Lesen von Stream.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top