Как переместить миллионы файлов в другой файл в том же контейнере в Azure Blob Storage? - PullRequest
0 голосов
/ 13 января 2020

У нас есть миллионы записей (как паркет, так и json файлы) в Azure Хранилище BLOB-объектов в виде структуры:

/ RecordName / Год / Месяц / День / Час / ParquetOrJsonFiles.parquetOr json

Есть ок. 5 миллионов файлов в этой структуре, и я хочу изменить путь к папке следующим образом:

/ Год / Месяц / День / Часы / Имя записи / ParquetOrJsonFiles.parquetOr json

Я создал Сценарий basi c в DataBricks python Записная книжка выглядит следующим образом: 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)

Однако этот сценарий работает очень медленно. Есть ли способ быстрее двигаться?

1 Ответ

1 голос
/ 13 января 2020

На самом деле, отсутствует API REST Azure Хранилище больших двоичных объектов, которое поддерживало бы переименование операции для большого двоичного объекта, поэтому реальные операции для переименования большого двоичного объекта - сначала его скопировать, а затем удалить. Функция os.rename, действующая в dbfs, также выполняет операции копирования и удаления по порядку. Это реальная причина замедления работы вашего сценария.

Решение, использующее API REST, заключается в том, чтобы сначала выполнить Copy Blob From URL для каждого большого двоичного объекта в контейнере, а затем - * 1009. * для всех оригинальных BLOB-объектов в Blob Batch.

Вот мой пример кода с использованием функций start_copy_from_url, delete_blobs самого последнего Azure Storage SDK для Python (v12) , которые устанавливаются через 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...