python dask to_parquet占用大量内存

时间:2019-08-04 07:06:11

标签: python dataframe dask parquet fastparquet

我正在使用带有dask的python 3来读取实木复合地板文件列表,进行一些处理,然后将其全部放入一个新的统一实木复合地板文件中以备后用。

该进程占用了太多内存,似乎试图将所有实木复合地板文件读入内存,然后再将其写入新的实木复合地板文件中。

我正在使用以下代码

def t(path):
    import dask.dataframe as dd
    ddf = dd.read_parquet(path)
    ddf["file"] = path
    return ddf

b = bag.from_sequence(parquet_files)
with ProgressBar():
       data = b.map(lambda x: t(x)).\
              map(lambda y: dd.to_parquet(y, output_parquet_file, partition_on=["file"], append=True, engine="fastparquet")).\
           compute(num_workers=1)

每次使用一个工作程序时,尤其是使用更多工作程序时,内存都会爆炸。文件很大(每个文件大约1G),我试图从csv文件中读取信息并将它们分成25M块,并遇到了同样的问题。

我在这里想念什么?当似乎迭代过程是正确的选择时,为什么它尝试将所有内容加载到内存中?如何在不消耗那台机器上128G内存的情况下使用dask操作呢?

PS,我尝试使用pyarrow引擎,但问题是dask尚未实现append。

编辑:尝试过的建议解决方案: 我现在尝试此代码

import dask.dataframe as dd
with ProgressBar():
    dfs = [dd.read_parquet(pfile) for pfile in parquet_files]
    for i, path in enumerate(parquet_files):
        dfs[i]["file"] = path
    df = dd.concat(dfs)
    df.to_parquet(output_parquet_file)

而且,内存爆炸(在具有200G以上内存的系统上)

2 个答案:

答案 0 :(得分:2)

在另一个集合上的地图中使用dask集合方法很奇怪。您可以像这样使用bag.map并直接调用fastaprquet函数,或者可能更好(取决于您需要执行的处理),使用dataframe API进行所有操作:

dfs = [dd.read_parquet(pfile, ...) for pfile in parquet_files]
df = dd.concat(dfs)
df.to_parquet(...)

请注意,尽管您尝试附加到单个文件(我认为),镶木地板格式并不能真正从中受益,您也可以让Dask为每个分区写一个文件。

答案 1 :(得分:0)

dask 支持将多个 parquet 文件作为分区读取。 直接调用就行了。

import dask.dataframe as dd
ddf = dd.read_parquet("parquets/*.parquet")
ddf = ddf.map_partitions(lambda df: df*2)
ddf.to_parquet("result.parquet")