将大熊猫DataFrame保存到S3的最快方法是什么?

时间:2019-03-28 18:09:28

标签: python-3.x pandas amazon-s3

我正在尝试找出将大熊猫DataFrame写入S3文件系统的最快方法。我目前正在尝试两种方法:

1)通过gzip压缩(BytesIO)和boto3

gz_buffer = BytesIO()

with gzip.GzipFile(mode='w', fileobj=gz_buffer) as gz_file:
    df.to_csv(TextIOWrapper(gz_file, 'utf8'), index=False)

s3_resource = boto3.resource('s3')
s3_object = s3_resource.Object(bucket, s3_path + name_zip)
s3_object.put(Body=gz_buffer.getvalue())

对于700万行的数据帧,大约需要420秒才能写入S3。

2)通过不压缩即可写入csv文件(StringIO缓冲区)

csv_buffer = StringIO()
data.to_csv(csv_buffer)
s3_resource = boto3.resource('s3')
s3_resource.Object(bucket, s3_path + name_csv).put(Body=csv_buffer.getvalue())

这大约需要371秒...

问题是: 还有其他更快的方法可以将熊猫数据帧写入S3吗?

4 个答案:

答案 0 :(得分:3)

使用分段上传可以更快地传输到S3。压缩使文件更小,因此也有帮助。

import boto3
s3 = boto3.client('s3')

csv_buffer = BytesIO()
df.to_csv(csv_buffer, compression='gzip')

# multipart upload
# use boto3.s3.transfer.TransferConfig if you need to tune part size or other settings
s3.upload_fileobj(csv_buffer, bucket, key)

s3.upload_fileobj的文档在这里:https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.upload_fileobj

答案 1 :(得分:0)

您可以尝试将if (value) { snapshot.forEach(function (childSnapshot) { var myDate = childSnapshot.val(); days.push(new Date(myDate.date)); //ARRAY DOES NOT SORT, yet... }); days.sort(date_sort_asc); // <-- Do it here } s3fs压缩一起使用,以上传到S3。 pandasStringIO占用内存。

BytesIO

答案 2 :(得分:0)

首先,检查您是否正在写与笔记本位于相同区域的存储桶。

第二,您可以尝试使用 multi-part 进行上传的选项,该方法可以接收大于几GB的文件并并行上传:

from boto3.s3.transfer import TransferConfig

def s3_upload_file(args):     
    s3 = boto3.resource('s3')

    GB = 1024 ** 3
    config = TransferConfig(multipart_threshold=5 * GB)

    s3.meta.client.upload_file(args.path, args.bucket, os.path.basename(args.path),Config=config)

答案 3 :(得分:0)

这确实取决于内容,但这与boto3无关。首先尝试将DataFrame本地转储,看看最快的速度和您得到的大小。

以下是一些我们发现很快的建议,对于几MB到超过2GB的情况(尽管对于超过2GB的情况,您确实需要镶木地板并将其拆分为镶木地板数据集):

  1. 很多混合的文本/数字数据(面向SQL的内容):使用df.to_parquet(file)

  2. 大多数数值数据(例如,如果您的列df.dtypes表示一个快乐的numpy单一类型的数组,而不是Object):则可以尝试df_to_hdf(file, 'key')

一点建议:尝试将df分成一些对您有意义的碎片(例如,按时间序列划分时间)。尤其是如果您对单个分片(例如,时间序列中的最后一个分片)进行了大量更新,那么下载/上传的速度将大大提高。

我们发现,HDF5体积更大(未压缩),但是它们从内存中快速地保存/加载到内存中。实木复合地板默认情况下是经过快速压缩的,因此它们通常会较小(当然,这取决于数据的熵;如果保存完全随机数,则会对您造成不利影响)。

对于boto3客户端,默认情况下multipart_chunksizemultipart_threshold均为8MB,这通常是个不错的选择。您可以通过以下方式进行检查:

tc = boto3.s3.transfer.TransferConfig()
print(f'chunksize: {tc.multipart_chunksize}, threshold: {tc.multipart_threshold}')

此外,默认值是每次上传使用10个线程(除非对象的大小大于上述阈值,否则不会执行任何操作)。

另一个问题是如何有效地上传许多文件。 {strong> 不能通过TransferConfig中的任何定义来处理。但是我离题了,最初的问题是关于单个对象的。

相关问题