Wie kann ich schnell auf die Daten in vielen großen CSV-Dateien von Perl aus zugreifen?

7

Ich habe eine Reihe von Skripten, die derzeit viele Daten aus einigen .CSV-Dateien lesen. Aus Effizienzgründen benutze ich das Modul Text :: CSV_XS , um sie einzulesen und dann einen Hash zu erstellen die Spalten als Index. Ich habe jedoch eine Menge Dateien und sie sind ziemlich groß. Und jedes der Skripte muss die Daten erneut einlesen.

Die Frage ist: Wie kann ich diese Perl-Hashes persistent speichern, so dass alle mit einem Minimum an CPU zurück eingelesen werden können?

Die Kombination der Skripte ist keine Option. Ich wünschte ...

Ich habe die zweite Regel der Optimierung angewendet und Profiling verwendet, um festzustellen, dass die überwiegende Mehrheit der CPU (ca. 90%) darin war:

%Vor%

Also habe ich ein Testskript erstellt, das alle .CSV-Dateien ( Text :: CSV_XS ) einliest, sie mit dem speicherbaren -Modul ausgibt und dann zurückgeht und lies sie mit dem Modul Speicherbar zurück. Ich profilierte das so, dass ich die CPU-Zeiten sehen konnte:

%Vor%

Die Verwendung von Speicherfähig kostet etwa 25,6%, um wieder geladen zu werden, verglichen mit Text :: CSV_XS bei etwa 35%. Nicht viel Ersparnisse ...

Hat jemand einen Vorschlag, wie ich diese Daten effizienter einlesen kann?

Danke für Ihre Hilfe.

    
Harold Bamford 24.07.2009, 20:34
quelle

5 Antworten

9

Analysiere die Daten einmal und lege sie in eine SQLite db . Abfrage mit DBI .

    
Sinan Ünür 24.07.2009, 20:40
quelle
11

Der einfachste Weg, einen sehr großen Hash auf die Festplatte zu stellen, ist BerkeleyDB . Es ist schnell, erprobt und stabil, und das CPAN-Modul bietet eine gebundene API. Das bedeutet, dass Sie Ihren Hash weiterhin verwenden können, als ob er eine speicherinterne Datenstruktur wäre. Er liest und schreibt jedoch automatisch BerkeleyDB auf die Festplatte.

    
friedo 24.07.2009 21:58
quelle
3

Nun, ich habe den Vorschlag von Sinan Ünür (danke!) angenommen und eine SQLite-Datenbank erstellt und mein Testprogramm erneut ausgeführt, um die Daten über CSV-Dateien verglichen mit den Daten aus der SQLite-Datenbank zu vergleichen :

%Vor%

Die Summe für CSV_XS ist 34,67% im Vergleich zu 20,63% für SQLite, was etwas besser ist als die Storable-Lösung, die ich zuvor versucht habe. Dies ist jedoch kein fairer Vergleich, da ich mit der CSV_XS-Lösung die komplette CSV-Datei laden muss, aber mit der SQLite-Schnittstelle kann ich einfach die Teile laden, die ich möchte. In der Praxis erwarte ich daher noch mehr Verbesserung, als dieser einfältige Test zeigt.

Ich habe nicht versucht, BerkeleyDB (sorry, friedo) anstelle von SQLite zu verwenden, hauptsächlich weil ich diesen Vorschlag nicht sah, bis ich mich mit dem Ausprobieren von SQLite beschäftigt hatte. Das Einrichten des Tests war eine nicht-triviale Aufgabe, da ich fast nie Gelegenheit hatte, SQL-Datenbanken zu verwenden.

Die Lösung besteht eindeutig darin, alle Daten in eine Datenbank zu laden und über das DBI-Modul zuzugreifen. Danke für die Hilfe von allen. Alle Antworten werden sehr geschätzt.

    
Harold Bamford 27.07.2009 18:32
quelle
2

Es ist sehr zu empfehlen, die gesamte Liste nicht jedes Mal in den Speicher zu laden, wenn Sie das Skript ausführen. Mit einer Datenbank auf der Festplatte können Sie dies tun. Wenn Sie bei jedem Start aus irgendeinem Grund jeden Eintrag in der CSV-Datei berühren müssen, empfehle ich Ihnen, ihn auf einer RAM-Disk anstelle einer physischen Festplatte zu speichern. Es passt offensichtlich in den Speicher, ich glaube nicht, dass Sie viel Verbesserung erfahren werden, indem Sie das Format auf der Festplatte ändern, in dem Sie es speichern. Die einzige Möglichkeit, es wirklich zu beschleunigen, ist, es auf einem schnelleren Medium zu speichern.

    
bmdhacks 24.07.2009 21:07
quelle
1

Wenn Sie nur auf einen Teil der Daten in jedem Skript zugreifen müssen, statt auf ALLES, DBM :: Deep ist wahrscheinlich die beste Wahl.

Disk / IO ist wahrscheinlich Ihr größter Engpass, egal was Sie tun. Vielleicht könnten Sie einen Datenprovider verwenden, der alle verfügbaren Daten in einem milliardierten Cache speichert - mit etwas wie Sys: : Mmap :: Simple Ich musste nie so etwas tun, also habe ich nicht viel mehr zu bieten.

    
daotoad 24.07.2009 22:28
quelle

Tags und Links