将整个(大)架构转换为 hdf5

Posted

技术标签:

【中文标题】将整个(大)架构转换为 hdf5【英文标题】:Convert the whole (large) schema into hdf5 【发布时间】:2020-01-30 00:17:09 【问题描述】:

我正在尝试使用 postgreSQL 查询导出整个数据库架构(大约 20 GB)以创建最终唯一的 hdf5 文件。

因为这个大小不适合我的计算机内存,所以我使用了 chuncks 参数。

首先我使用这个函数建立连接:

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】:

我建议直接使用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) 为我描述了 complevelcomplib

【讨论】:

嗨,山姆,感谢您的回答。看看我更新的例子是否像你建议的那样 当我运行这个函数时,输出文件被创建,但没有数据。 嗨 Sam,这与 dtypes 和列大小问题有关。 很高兴为您提供帮助!请注意,您可以做很多事情来使事情变得更快,例如***.com/a/20084843/1358308中的各种建议 嗨 Sam,我遇到了一个错误:服务器意外关闭了连接这可能意味着服务器在处理请求之前或期间异常终止。

以上是关于将整个(大)架构转换为 hdf5的主要内容,如果未能解决你的问题,请参考以下文章

将大 csv 转换为 hdf5

将 HDF5 文件转换为其他格式

在不加载到内存的情况下将 HDF5 转换为 Parquet

将数百个 csv 文件转换为 hdf5 文件

如何从 hdf5 保存/提取数据集并转换为 TiFF?

如何将这种类型的数据 <hdf5 object reference> 转换为 python 中更易读的东西?