如何使用Dask从Google云端存储中读取多个大型CSV文件的块,而不会一次使所有内存过载

时间:2019-06-30 08:52:49

标签: python pandas postgresql dask dask-distributed

我正在尝试从Google存储设备读取一堆大的csv文件(多个文件)。我使用 Dask 分发库进行并行计算,但是我在这里面临的问题是,尽管我提到了 blocksize(100mb),但我不确定如何逐分区读取分区,并将其保存到我的 postgres 数据库中,这样我就不会过载内存。

    from dask.distributed import Client
    from dask.diagnostics import ProgressBar
    client = Client(processes=False)
    import dask.dataframe as dd

    def read_csv_gcs():
      with ProgressBar():
        df = dd.read_csv('gs://mybucket/renish/*.csv', blocksize=100e6)
        pd = df.compute(scheduler='threads')
        return pd

    def write_df_to_db(df):
      try:
        from sqlalchemy import create_engine
        engine = create_engine('postgresql://usr:pass@localhost:5432/sampledb')
        df.to_sql('sampletable', engine, if_exists='replace',index=False)
      except Exception as e:
        print(e)
        pass

    pd = read_csv_gcs()
    write_df_to_db(pd)

上面的代码是我的基本实现,但是正如我所说,我想分块读取它并更新数据库。像

    df = dd.read_csv('gs://mybucket/renish/*.csv', blocksize=100e6)
    for chunk in df:
       write_it_to_db(chunk)

是否可以在 Dask中完成它??还是应该选择pandas的块大小并进行迭代,然后将其保存到DB中(但是我在这里错过了并行计算)?

有人可以照亮吗?

1 个答案:

答案 0 :(得分:1)

此行

df.compute(scheduler='threads')

说:在工作线程中以块的形式加载数据,并将它们全部串联到单个内存数据帧df中。这不是您想要的。您想在块插入时插入它们,然后将其从内存中删除

您可能想使用map_partitions

df = dd.read_csv('gs://mybucket/renish/*.csv', blocksize=100e6)
df.map_partitions(write_it_to_db).compute()

或使用df.to_delayed()

请注意,根据您的SQL驱动程序,您可能无法以这种方式获取并行性,否则,pandas的iter-chunk方法将同样有效。