2016-07-10 20 views
0

Ich möchte eine verschlüsselte 500 GB-800 GB-Tabelle in HDF5 speichern und dann Zeilen mit bestimmten Schlüsseln abrufen.Verwenden von PyTables zum Indexieren einer HDF5-Datei mit 500 GB

Für eine HDF5 Datei, Elemente wie alle Datenzugriff verwenden eine ganze Zahl „Zeilen“ Zahl, so scheint wie ich Nummer Karte“einen‚Schlüssel müsste implementieren außerhalb von HDF5 zu bringen.

Würde dieser Arbeit "Muss ich auf das gesamte HDF5" im Speicher (RAM) "zugreifen?

Kann jemand mir ein Gefühl geben, wie schlecht HDF5 in dieser Situation durchführen würde? Wenn es annehmbare Indizierung gibt, ist das nur ein riesiges Wörterbuch, richtig?

Sollte ich etwas anderes verwenden?

+0

PyTables unterstützt Indizes für Spalten (siehe [hier] (http://www.pytables.org/usersguide/optimization.html#indexed-searches) mit 'numexpr' mit dem OPSI. Index sollte schnell genug sein und sollte nicht alles in den Speicher zu lesen benötigen –

+0

@ Ümit Thanks for this.Dies ist eigentlich eine ziemlich gute Idee.Können Sie ein schnelles Beispiel unten bieten? zB make-Tabelle, setzen OSPI-Indizes auf eine Hand voll von Spalten mit PyTables, benutze numexpr, um zu zeigen, wie dies gemacht wird, etc. Es ist einfacher zu folgen, und nützlich für StackExchange – ShanZhengYang

+0

hinzugefügt eine Antwort –

Antwort

5

Angenommen, Sie diesen Satzart in PyTables definiert haben

class Record(tables.IsDescription): 
    row = tables.Int32Col() 
    col1 = tables.Int32Col() 
    col2 = tables.Float64Col() 
    col3 = tables.Float64Col() 

Eine regelmäßige Bereichsabfrage könnte wie folgt aussehen:

result = [rec for rec in table if (rec['row'] > 100 and rec['row'] < 200)] 

Dieses feinen Ihre Tabelle funktioniert nicht zu groß ist. Für große Tabellen wird es jedoch relativ langsam sein, da jede Zeile in den Python-Raum gebracht werden muss, um für die Bereichsbedingung ausgewertet zu werden.

Um diese Abfrage zu beschleunigen man auf die so genannte im Kernel Abfragen verlassen kann, die die Bedingung mit einem PyTables Kernel überprüfen können, die mit Hilfe der numexpr Bibliothek in C geschrieben wird.

result = [rec for rec in table.where(
      'row > 100 & row < 200')] 

Sie können auch eine regelmäßige Abfrage mit einer in-kernel Abfrage mischen und:

result = [rec for rec in table.where(
      'row > 100 & row < 200')] if your_function(rec['col2']) ] 

Wenn Sie große Tabellen, die in den Speicher passen nicht der Speedup um 2x ist. Die Verwendung von Komprimierung (d. H. BLOSC, LZF usw.) führt zu einer leichten Geschwindigkeitssteigerung, da der CPU-Overhead des Dekomprimierens geringer ist als der I/O-Overhead (verwenden Sie also die Komprimierung für große Tabellen, die nicht in den Speicher passen).

Wenn Sie die Komprimierung verwenden, wird das Dataset in Chunks aufgeteilt und die Chunks werden separat komprimiert. Das heißt, wenn Sie nach einem bestimmten Bereich (Zeilen 100 - 200) fragen, werden die entsprechenden komprimierten Blöcke von der Festplatte in den Speicher geladen und dann von der CPU im Speicher dekomprimiert. Dies wird die Geschwindigkeit im Vergleich zur Verwendung ohne Komprimierung oder zum kontinuierlichen Speichern des Datasets beschleunigen. Blosc ist ein Meta-Kompressor und lzf ist der Standardkompressor von h5py. Für Unterschiede zwischen Blosc und lzf siehe thread.

Wenn die In-Kernel-Abfragen nicht schnell genug sind, können Sie auch einen Index für eine oder mehrere Spalten erstellen. Auf diese Weise wird die Abfrage eine binäre Suche anstelle einer sequenziellen Suche verwenden. So erstellen Sie führen einen Index für eine vorhandene Tabelle für die row Spalte gerade:

indexrows = table.cols.row.create_index() 

Aber Vorsicht, dass der Index nicht auf allen Bedingungen verwendet werden (siehe Referenz unten). Um zu überprüfen, ob Ihre Abfrage den Index ordnungsgemäß verwendet, können Sie die Methode Table.will_query_use_indexing() verwenden.

Quelle: http://www.pytables.org/usersguide/optimization.html#indexed-searches

+0

"Die Verwendung von Komprimierung (zB BLOSC, LZF, etc) gibt Ihnen eine leichte Geschwindigkeitsstoß als CPU-Overhead des Dekomprimierens ist le ss als der E/A-Overhead (verwenden Sie also die Komprimierung für große Tabellen, die nicht in den Speicher passen). "Ich bin mir nicht sicher, ob ich dem folge. 500 GB passen nicht in den Arbeitsspeicher. Gibt es einen Leistungsunterschied zwischen BLOSC und LZF? Können Sie oben skizzieren, wie Sie Daten komprimieren? (Sorry --- brauchen nur ein paar mehr Details, um den Beitrag umfassend zu machen. Danke!) – ShanZhengYang

+0

Gibt es auch einen Unterschied in Bezug auf BLOSC vs LZF? Danke für jede Hilfe! – ShanZhengYang

+0

Ich aktualisierte die Antwort oben –