【问题标题】:How to move millions of file to another file in the same container in Azure Blob Storage?如何将数百万个文件移动到 Azure Blob 存储中同一容器中的另一个文件?
【发布时间】:2020-04-30 00:30:09
【问题描述】:

我们在 Azure Blob 存储中有数百万条记录(parquet 和 json 文件),结构如下:

/RecordName/Year/Month/Day/Hour/ParquetOrJsonFiles.parquetOrjson

大约有。该结构中有 500 万个文件,我想将文件夹路径重塑为:

/年/月/日/小时/记录名称/ParquetOrJsonFiles.parquetOrjson

我在 DataBricks python notebook 中创建了一个基本脚本,如下所示: ps:容器已经安装在我的工作区中。

import os

target_file = '/dbfs/containername/RecordName/Year/Month/Day/Hour/ParquetOrJsonFiles.parquetOrjson'
destination_file = '/dbfs/Year/Month/Day/Hour/RecordName/ParquetOrJsonFiles.parquetOrjson'

os.rename(target_file, destination_file)

但是,这个脚本运行起来非常缓慢。有什么方法可以加快移动速度?

【问题讨论】:

    标签: python azure azure-blob-storage databricks azure-databricks


    【解决方案1】:

    实际上,Azure Blob Storage 没有任何 REST API 支持对 blob 进行重命名操作,因此重命名 blob 的真正操作是先复制它,然后再删除它。在dbfs 中运行的os.rename 函数也是按顺序进行复制和删除操作。这才是让你的脚本变慢的真正原因。

    使用 REST API 的解决方案是首先对容器中的每个 blob 执行 Copy Blob From URL,然后对 Blob Batch 中的所有原始 blob 执行 Delete Blob

    这是我使用最新 Azure Storage SDK for Python (v12) 的函数 start_copy_from_urldelete_blobs 的示例代码,通过 pip install azure-storage-blob 安装。

    from azure.storage.blob import BlobServiceClient
    
    account_name = '<your account name>'
    account_key = '<your account key>'
    connection_string = f"AccountName={account_name};AccountKey={account_key};EndpointSuffix=core.windows.net;DefaultEndpointsProtocol=https;"
    blob_service_client = BlobServiceClient.from_connection_string(connection_string)
    
    container_name = '<your container name>'
    
    container_client = blob_service_client.get_container_client(container_name)
    
    blobs = list(container.list_blobs())
    
    # Copy all blobs with a new name to the same container
    for blob in blobs:
        blob_name = blob.name
        source_url = f"https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}"
        record_name, year, month, day, hour, name = blob_name.split('/')
        new_blob_name = f'{year}/{month}/{day}/{hour}/{record_name}/name'
        copied_blob = blob_service_client.get_blob_client(container_name, new_blob_name)
        copied_blob.start_copy_from_url(source_url)
    
    # Delete all original blobs
    delete_blob_list = [b.name for b in blobs]
    container_client.delete_blobs(*delete_blob_list)
    

    【讨论】:

    • start_copy 的 python 版本是否像 C# 版本一样运行服务器端,因为这比旧的复制操作快得多。如果不是,我建议使用 AZCopy 工具,因为它会在服务器端进行复制。
    猜你喜欢
    • 1970-01-01
    • 2016-11-29
    • 2018-01-25
    • 2020-07-21
    • 2021-03-13
    • 1970-01-01
    • 2017-08-18
    • 2020-09-24
    相关资源
    最近更新 更多