Конвертировать всю (большую) схему в hdf5 - PullRequest
0 голосов
/ 30 сентября 2019

Я пытаюсь экспортировать всю схему базы данных (около 20 ГБ), используя запрос postgreSQL для создания окончательного уникального файла hdf5.

Поскольку этот размер не помещается в память моего компьютера, я использую чанкиАргумент.

Сначала я использую эту функцию для установления соединения:

def make_connectstring(prefix, db, uname, passa, hostname, port):
    """return an sql connectstring"""
    connectstring = prefix + "://" + uname + ":" + passa + "@" + hostname + \
                    ":" + port + "/" + db
    return connectstring

Затем я создал временную папку для сохранения каждого файла hdf5.

def query_to_hdf5(connectstring, query, verbose=False, chunksize=50000):

    engine = sqlalchemy.create_engine(connectstring, 
        server_side_cursors=True)    

    # get the data to temp chunk filese
    i = 0
    paths_chunks = []
    with tempfile.TemporaryDirectory() as td:
        for df in pd.read_sql_query(sql=query, con=engine, chunksize=chunksize):
            path = td + "/chunk" + str(i) + ".hdf5"
            df.to_hdf(path, key='data')
            print(path)
            if verbose:
                print("wrote", path)
            paths_chunks.append(path)
            i+=1


connectstring = make_connectstring(prefix, db, uname, passa, hostname, port)
query = "SELECT * FROM public.zz_ges"
df = query_to_hdf5(connectstring, query)

Что такоелучший способ объединить все эти файлы в один файл, представляющий весь фрейм данных?

Я пробовал что-то вроде этого:

    df = pd.DataFrame()
    print(path)
    for path in paths_chunks:
        df_scratch = pd.read_hdf(path)
        df = pd.concat([df, df_scratch])
        if verbose:
            print("read", path)

Однако память очень быстро увеличивается. Мне нужно что-то, что могло бы быть более эффективным.

Обновление:

def make_connectstring(prefix, db, uname, passa, hostname, port):
    """return an sql connectstring"""
    connectstring = prefix + "://" + uname + ":" + passa + "@" + hostname + \
                    ":" + port + "/" + db
    return connectstring

def query_to_df(connectstring, query, verbose=False, chunksize=50000):

    engine = sqlalchemy.create_engine(connectstring, 
        server_side_cursors=True)    

    # get the data to temp chunk filese
    with pd.HDFStore('output.h5', 'w') as store:
        for df in pd.read_sql_query(sql=query, con=engine, chunksize=chunksize):
            store.append('data', df)

1 Ответ

1 голос
/ 30 сентября 2019

Я бы предложил использовать HDFStore напрямую, чтобы вы могли добавлять чанки по мере их получения из базы данных, например:

with pd.HDFStore('output.h5', 'w') as store:
  for df in pd.read_sql_query(sql=query, con=engine, chunksize=chunksize):
    store.append('data', df)

Это основано наВаш существующий код не является полным, дайте мне знать, если он не ясен

примечание: я открываю магазин в режиме w, поэтому он будет удалять файл каждый раз. в противном случае append будет просто добавлять те же строки в конец таблицы. в качестве альтернативы вы могли бы remove сначала ввести ключ

, когда вы открываете магазин, вы также можете использовать множество опций, таких как сжатие, но оно не очень хорошо документировано, help(pd.HDFStore) описывает complevel и complib для меня

...