2016-12-13 4 views
0

Ich habe ein viele große 1-D hdf5 Datensätze mit folgenden Eigenschaften:Umzug von HDF5 zu PostgreSQL

  • init size = (5201,),
  • maxshape = (6000000,),
  • dtype = 'float32'
  • chunks = (10000)
  • compression = "gzip"
  • Pfad Beispiel: file [ "Gruppe"] [ "1"] [ "Gruppe 1"] [ "2"] [“ Datensatz "]

Ich möchte sie in die PostgreSQL verschieben, ich habe mit Struktur der Datenbank und Einfügen von Daten, aber jede Füllung dauert ~ 650 Sekunden von 72,4 MB hdf5 Datei, kann mir jemand eine Tipps/Ratschläge geben, wie ich die verbessern kann Performance?

Was ich habe jetzt:

def fill_database(self, dog): 
    if isinstance(dog, h5py.Dataset): 
     name = dog.name.split('/') 
     table_name = '{}_{}'.format(name[3], name[5]) 
     data = dog.value.astype(int).tolist() 
     self.cur.execute('CREATE TABLE IF NOT EXISTS {} (cur_id INT PRIMARY KEY , data INT[]);'.format(table_name)) 
     self.cur.execute('INSERT INTO {} VALUES (%s, %s)'.format(table_name), (name[2], data)) 

     if isinstance(dog, h5py.Group): 
      for k, v in dict(dog).items(): 
       self.fill_database(v) 

Was ich versuchte:

import psycopg2 
import h5py 
from itertools import islice 


with h5py.File('full_db.hdf5') as hdf5file: 
    with psycopg2.connect(database='hdf5', user='postgres', password='pass', port=5432) as conn: 
     cur = conn.cursor() 
     cur.execute('drop table if EXISTS mytable;') 
     cur.execute('create table mytable (data INT[]);') 
     chunksize = 10000 
     t = iter(hdf5file["Group"]["1"]["Group1"]["2"]["Dataset"][:].astype(int)) 
     rows = islice(t, chunksize) 
     while rows: 
      statement = "INSERT INTO mytable(data) VALUES {}".format(rows) # I stuck here 
      cur.execute(statement) 
      rows = islice(t, chunksize) 
     conn.commit() 

Auch habe ich versucht, etwas mit LIMIT in PostgreSQL und vielen anderen Möglichkeiten zu tun, aber ich war nicht erfolgreich.

Ich denke, einige der Probleme können aufgrund von Arrays in der Datenbank, ich verwende sie für später bequemer Ausgabe.

Antwort

0

Nach fast zwei Wochen denke ich, dass ich meine eigene Frage beantworten kann. Auf der Suche nach einer Antwort kam ich im Internet auf dieser Seite https://github.com/psycopg/psycopg2/issues/179 Auch nach dem Lesen der Dokumentation verstand ich, dass ein Kopieren von einer Datei noch schneller funktioniert und ich versuchte, das Modul von StringIO zu verwenden. Und das ist, was ich bekommen:

import h5py 
import psycopg2 
import time 
from io import StringIO 

conn = psycopg2.connect(database='hdf5', user='postgres', password=' ') 
cur = conn.cursor() 

file = h5py.File('db.hdf5', 'r') 
data_set = file['path/to/large/data_set'].value.astype(int).tolist() 

cur.execute('DROP TABLE IF EXISTS table_test;') 
cur.execute('CREATE TABLE table_test (data INTEGER[]);') 

# ORIGINAL 
start = time.time() 
cur.execute('INSERT INTO table_test VALUES (%s);', (data_set,)) 
print('Original: {} sec'.format(round(time.time() - start, 2))) 

# STRING FORMAT 
start = time.time() 
data_str = ','.join(map(str, data_set)).replace('[', '{').replace(']', '}') 
cur.execute('INSERT INTO table_test VALUES (ARRAY[{}]);'.format(data_str)) 
print('String format: {} sec'.format(round(time.time() - start, 2))) 

# STRING IO COPY 
start = time.time() 
data_str = ','.join(map(str, data_set)).replace('[', '{').replace(']', '}') 
data_io = StringIO('{{{}}}'.format(data_str)) 
cur.copy_from(data_io, 'table_test') 
print('String IO: {} sec'.format(round(time.time() - start, 2))) 

conn.commit() 

Was mich mit Datensatz mit Form nächste Ergebnis gibt (1200201):

Original: 1.27 sec 
String format: 0.58 sec 
String IO: 0.3 sec