簡體   English   中英

從HDF5遷移到PostgreSQL

[英]Moving from HDF5 to PostgreSQL

我有許多具有下一屬性的大型一維hdf5數據集:

  • 初始大小=(5201,),
  • maxshape =(6000000,),
  • dtype ='float32'
  • 塊=(10000,)
  • 壓縮=“ gzip”
  • 路徑示例:file [“ Group”] [“ 1”] [“ Group1”] [“ 2”] [“ Dataset”]

我想將它們移到PostgreSQL中,我處理了數據庫的結構並插入了數據,但是每次填充需要大約650秒的72,4mb hdf5文件,有人可以給我一些提示/建議來改善性能嗎?

我現在所擁有的:

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)

我試過的

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()

我也嘗試在PostgreSQL和其他許多方式中使用LIMIT進行操作,但未成功。

我認為某些問題可能是由於數據庫中的數組所致,我將它們用於以后更方便的輸出。

近兩周后,我想我可以回答我自己的問題。 為了尋找答案,我在Internet上的此頁面上遇到了https://github.com/psycopg/psycopg2/issues/179另外,在閱讀了文檔后,我了解到從文件進行復制的速度更快,因此我嘗試了使用StringIO的模塊。 那就是我得到的:

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()

這給了我一個形狀為(1200201,)的數據集的下一個結果:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM