簡體   English   中英

使用 boto3 在 S3 存儲桶中移動對象的最快方法

[英]Fastest way to move objects within an S3 bucket using boto3

我需要將所有文件從 S3 中的一個前綴復制到同一存儲桶中的另一個前綴。 我的解決方案是這樣的:

file_list = [List of files in first prefix]
for file in file_list:
            copy_source = {'Bucket': my_bucket, 'Key': file}
            s3_client.copy(copy_source, my_bucket, new_prefix)

然而,我只移動了 200 個小文件(每個 1 kb),這個過程最多需要 30 秒。 一定有可能做得更快嗎?

我會並行執行 例如:

from multiprocessing import Pool

file_list = [List of files in first prefix]
    
print(objects_to_download)

def s3_coppier(s3_file):
     copy_source = {'Bucket': my_bucket, 'Key': s3_file}
     s3_client.copy(copy_source, my_bucket, new_prefix)

# copy 5 objects at the same time
with Pool(5) as p:
    p.map(s3_coppier, file_list)

所以你有一個函數需要調用一堆東西,所有這些東西都是相互獨立的。 您可以嘗試多處理。

from multiprocessing import Process

def copy_file(file_name, my_bucket):
    copy_source = {'Bucket': my_bucket, 'Key': file_name}
    s3_client.copy(copy_source, my_bucket, new_prefix)

def main():
    file_list = [...]

    for file_name in file_list:
        p = Process(target=copy_file, args=[file_name, my_bucket])
        p.start()

然后它們都可以(大約)同時開始,而不必等待最后一個文件完成。

所以我做了一個小實驗,將 500 個 1kB 小文件從同一個 S3 存儲桶移動到同一個存儲桶 3,從 AWS 中的 Lambda(1024 MB ram)運行。 我對每種方法都做了 3 次嘗試。

嘗試 1 - 使用 s3_client.copy:31 - 32 秒

嘗試 2 - 使用 s3_client.copy_opbject:22 - 23 秒

嘗試 3 - 使用多處理、池(上面的答案):19 - 20 秒

有沒有可能做得更快?

我知道這是一篇舊帖子,但也許有人會像我一樣來到這里,想知道最優雅的方式 (IMO) 是什么。

awswrangler 復制方法文檔

如果我們使用awswrangler PyPi package,我們可以獲得良好的性能並以零努力並行執行。

根據os.cpu_count()返回的內容,它將盡可能多地利用線程。

import os
import botocore
import awswrangler as wr
import boto3

S3 = boto3.resource("s3")
bucket_name = os.environ["BUCKET_NAME"]
BUCKET = S3.Bucket(bucket_name)

def copy_from_old_path():
    source_prefix = "some_prefix"
    new_prefix = "some_new_prefix"
    objects = BUCKET.objects.filter(Prefix=source_prefix)
    keys_list = [obj.key for obj in objects]
    bucket_uri = f"s3://{bucket_name}"
    full_paths_list = [f"{bucket_uri}/{key}" for key in keys_list]  # key includes the source_prefix also
    source_path = f"{bucket_uri}/{source_prefix}/"
    target_path = f"{bucket_uri}/{new_prefix}/"
    wr.s3.copy_objects(full_paths_list, source_path, target_path)

if __name__ == "__main__":
    copy_from_old_path()

當從 Macbook M1 Pro(32 GB 內存)本地運行時,我花了大約 20 分鍾來復制 24.5 MB 的 4,475 個鑲木地板文件(每個大約 7 KB)。 在運行之前不要忘記在 CLI 中導出 AWS 憑證,並導出保存存儲桶名稱的環境變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM