dask.read_parquet导致OOM错误

时间:2018-08-08 15:01:43

标签: python parquet dask

我一直在使用dask对多个csv文件执行数据清理。这段代码可以正常工作:

import pandas as pd
import glob
import os
from timeit import default_timer
from dask.distributed import Client
import dask.dataframe as dd

cols_to_keep = ["barcode", "salesdate", "storecode", "quantity", "salesvalue", "promotion", "key_row"]

col_types = {'barcode': object,
            'salesdate': object,
            'storecode': object,
            'quantity': float,
            'salesvalue': float,
            'promotion': object,
            'key_row': object}

trans = dd.read_csv(os.path.join(TRANS_PATH, "*.TXT"), 
                    sep=";", usecols=cols_to_keep, dtype=col_types, parse_dates=['salesdate'])

trans = trans[trans['barcode'].isin(barcodes)]

trans_df = trans.compute()

我决定尝试使用实木复合地板存储系统,因为它据说速度更快,并且得到了dask的支持。使用熊猫的to_parquet()方法将csv文件转换为.parquet之后,我尝试了以下操作:

cols_to_keep = ["barcode", "salesdate", "storecode", "quantity", "salesvalue", "promotion", "key_row"]

trans = dd.read_parquet(os.path.join(PARQUET_PATH, '*.parquet'), columns=cols_to_keep)

trans = trans[trans['barcode'].isin(barcodes)]

trans_df = trans.compute()

图形开始执行后不久,工作进程内存不足,并且我收到多个警告:

distributed.nanny - WARNING - Worker exceeded 95% memory budget.  Restarting
distributed.nanny - WARNING - Worker process 13620 was killed by signal 15
distributed.nanny - WARNING - Worker exceeded 95% memory budget.  Restarting
distributed.nanny - WARNING - Restarting worker
distributed.nanny - WARNING - Worker exceeded 95% memory budget.  Restarting
distributed.nanny - WARNING - Worker exceeded 95% memory budget.  Restarting
distributed.nanny - WARNING - Worker exceeded 95% memory budget.  Restarting
distributed.nanny - WARNING - Worker exceeded 95% memory budget.  Restarting
distributed.nanny - WARNING - Worker process 13396 was killed by signal 15

最后,整个程序崩溃了。我的.parquet文件不是问题,我可以使用pandas的read_parquet()方法加载它们。从dask实用程序中,我注意到由于某种原因,该图试图在使用.isin调用执行任何过滤之前读取所有内容: graph execution with dd.read_parquet()

使用dd.read_csv()时不是这种情况。在这里,所有操作都是“并行”运行的,因此过滤可以防止OOM:

enter image description here

有人知道发生了什么吗?我想念什么?

1 个答案:

答案 0 :(得分:3)

您的问题是使用pandas.to_parquet()写入数据。这将在数​​据中创建单个庞大的行组,当Dask读取数据时,该行组将成为一个分区-Dask会遵循数据中的任何分区。相反,Dask会自动对CSV输入进行分区,而不假定数据具有固有的分区。

由于您已经在使用Dask,因此也应该使用它来编写地板数据,也可以使用dask.DataFrame.to_parquet(类似于Pandas方法)。它将在一个目录中产生多个文件,这些文件将被独立并并行读取。