programing

Azure 스토리지 컨테이너에서 BLOB 개수 가져오기

sourcetip 2023. 4. 22. 23:18
반응형

Azure 스토리지 컨테이너에서 BLOB 개수 가져오기

Azure 스토리지 컨테이너의 블럽 수를 계산하는 가장 효율적인 방법은 무엇입니까?

현재로선 아래 코드 외에 다른 방법이 없습니다.

CloudBlobContainer container = GetContainer("mycontainer");
var count = container.ListBlobs().Count();

코드를 쓰지 않고 컨테이너에 얼마나 많은 블럽이 있는지 알고 싶다면 Microsoft Azure Storage Explorer 응용 프로그램을 사용할 수 있습니다.

  1. 원하는 Blob Container를 엽니다.
  2. [ Folder Statistics ]아이콘을 클릭합니다.
  3. [ Activities ](액티비티) 창에서 블럽 수를 확인합니다.

ListBlobs()를 사용하여 blobs를 세어봤는데, 40만 개 정도의 용기는 5분 이상 걸렸습니다.

컨테이너를 완전히 제어할 수 있는 경우(즉, 쓰기 발생 시기를 제어할 수 있음) 컨테이너 메타데이터에 크기 정보를 캐시하고 항목을 제거하거나 삽입할 때마다 업데이트할 수 있습니다.다음은 컨테이너 BLOB 카운트를 반환하는 코드입니다.

static int CountBlobs(string storageAccount, string containerId)
{
    CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(storageAccount);
    CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
    CloudBlobContainer cloudBlobContainer = blobClient.GetContainerReference(containerId);

    cloudBlobContainer.FetchAttributes();

    string count = cloudBlobContainer.Metadata["ItemCount"];
    string countUpdateTime = cloudBlobContainer.Metadata["CountUpdateTime"];

    bool recountNeeded = false;

    if (String.IsNullOrEmpty(count) || String.IsNullOrEmpty(countUpdateTime))
    {
        recountNeeded = true;
    }
    else
    {
        DateTime dateTime = new DateTime(long.Parse(countUpdateTime));

        // Are we close to the last modified time?
        if (Math.Abs(dateTime.Subtract(cloudBlobContainer.Properties.LastModifiedUtc).TotalSeconds) > 5) {
            recountNeeded = true;
        }
    }

    int blobCount;
    if (recountNeeded)
    {
        blobCount = 0;
        BlobRequestOptions options = new BlobRequestOptions();
        options.BlobListingDetails = BlobListingDetails.Metadata;

        foreach (IListBlobItem item in cloudBlobContainer.ListBlobs(options))
        {
            blobCount++;
        }

        cloudBlobContainer.Metadata.Set("ItemCount", blobCount.ToString());
        cloudBlobContainer.Metadata.Set("CountUpdateTime", DateTime.Now.Ticks.ToString());
        cloudBlobContainer.SetMetadata();
    }
    else
    {
        blobCount = int.Parse(count);
    }

    return blobCount;
}

물론 컨테이너가 변경될 때마다 ItemCount/CountUpdateTime을 업데이트한다고 가정합니다.CountUpdateTime은 경험적 보호 수단이지만(누군가 CountUpdateTime을 업데이트하지 않고 컨테이너를 수정한 경우 강제로 재카운트를 수행함) 신뢰할 수 없습니다.

API에는 컨테이너 개수 메서드나 속성이 포함되어 있지 않으므로 게시한 내용과 같은 작업을 수행해야 합니다.단, 반환된 아이템이 5,000개를 넘었을 경우(또는 반환할 max #를 지정했을 경우, 리스트가 그 수를 넘었을 경우)에는 NextMarker를 취급해야 합니다.그런 다음 NextMarker에 따라 추가 호출을 하고 카운트를 추가합니다.

편집: SMARX 단위: SDK가 Next Marker를 대신 처리합니다.REST를 통해 List Blobs를 호출하고 API 수준에서 작업하는 경우 NextMarker를 처리해야 합니다.

또는 (예를 들어 wcf 서비스를 통해) blob 삽입/삭제를 제어하는 경우 blob 컨테이너의 메타데이터 영역을 사용하여 삽입 또는 삭제할 때마다 계산하는 캐시된 컨테이너 수를 저장할 수 있습니다.컨테이너에 대한 쓰기 동시성만 처리하면 됩니다.

PHP API와 getNextMarker를 사용하는 예.

Azure 컨테이너의 총 블럽 수를 카운트합니다.시간이 오래 걸린다. 10만 개의 방울에 30초 정도 걸린다.

(유효한 $connectionString과 $container_name이 있다고 가정합니다.)

$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($connectionString);
$opts = new ListBlobsOptions();
$nblobs = 0;

while($cont) {

  $blob_list = $blobRestProxy->listBlobs($container_name, $opts);      

  $nblobs += count($blob_list->getBlobs());

  $nextMarker = $blob_list->getNextMarker();

  if (!$nextMarker || strlen($nextMarker) == 0) $cont = false;
  else $opts->setMarker($nextMarker);
}
echo $nblobs;

가상 디렉토리를 사용하지 않는 경우는, 다음의 조작이 이전에 응답한 대로 동작합니다.

CloudBlobContainer container = GetContainer("mycontainer");
var count = container.ListBlobs().Count();

다만, 가상 디렉토리를 사용하고 있는 경우는, 상기의 코드 스니펫에 필요한 카운트가 없는 경우가 있습니다.

예를 들어, blobs가 /container/directory/filename과 유사하게 저장되어 있는 경우.txt. 여기서 blob name = directory/directory.컨테이너를 txt합니다.리스트 블롭스().Count();는 "/directory" 가상 디렉토리의 수만 카운트합니다.가상 디렉토리 내에 포함된 Blob을 나열하려면 ListBlobs() 호출에서 useFlatBlobListing = true를 설정해야 합니다.

CloudBlobContainer container = GetContainer("mycontainer");
var count = container.ListBlobs(null, true).Count();

주의: useFlatBlobListing = true의 ListBlobs() 콜은 훨씬 더 비싸고 느린 콜입니다.

다른 답변의 모든 성능 문제를 고려하여 Azure SDK의 v12 버전을 소개합니다.IAsyncEnumerable이를 위해서는 시스템에 대한 패키지 레퍼런스가 필요합니다.Linq.Async.

public async Task<int> GetBlobCount()
{
    var container = await GetBlobContainerClient();
    var blobsPaged = container.GetBlobsAsync();
    return await blobsPaged
        .AsAsyncEnumerable()
        .CountAsync();
}

Azure Storage의 Python API를 사용하면 다음과 같습니다.

from azure.storage import *
blob_service = BlobService(account_name='myaccount', account_key='mykey')
blobs = blob_service.list_blobs('mycontainer')
len(blobs)  #returns the number of blob in a container

Azure를 사용하고 있다면.보관소.Blobs 라이브러리에서는 다음과 같은 기능을 사용할 수 있습니다.

public int GetBlobCount(string containerName)
{
    int count = 0;
    BlobContainerClient container = new BlobContainerClient(blobConnctionString, containerName);
    container.GetBlobs().ToList().ForEach(blob => count++);
    return count;
}

또 다른 Python의 예는 5,000개 이상의 파일에서는 느리지만 올바르게 동작합니다.

from azure.storage.blob import BlobServiceClient

constr="Connection string"
container="Container name"

blob_service_client = BlobServiceClient.from_connection_string(constr)
container_client = blob_service_client.get_container_client(container)
blobs_list = container_client.list_blobs()

num = 0
size = 0
for blob in blobs_list:
    num += 1
    size += blob.size
    print(blob.name,blob.size)

print("Count: ", num)
print("Size: ", size)

아래의 해결책을 찾기 위해 꽤 오랜 시간을 소비했습니다.저 같은 사람이 시간을 낭비하고 싶지 않기 때문에, 9년이 지나도 여기에 회신해 주세요.

package com.sai.koushik.gandikota.test.app;

import com.microsoft.azure.storage.CloudStorageAccount;
import com.microsoft.azure.storage.blob.*;


public class AzureBlobStorageUtils {


    public static void main(String[] args) throws Exception {
        AzureBlobStorageUtils getCount =  new AzureBlobStorageUtils();
        String storageConn = "<StorageAccountConnection>";
        String blobContainerName = "<containerName>";
        String subContainer =  "<subContainerName>";
        Integer fileContainerCount = getCount.getFileCountInSpecificBlobContainersSubContainer(storageConn,blobContainerName, subContainer);
        System.out.println(fileContainerCount);
    }

    public Integer getFileCountInSpecificBlobContainersSubContainer(String storageConn, String blobContainerName, String subContainer) throws Exception {
        try {
            CloudStorageAccount storageAccount = CloudStorageAccount.parse(storageConn);
            CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
            CloudBlobContainer blobContainer = blobClient.getContainerReference(blobContainerName);
            return ((CloudBlobDirectory) blobContainer.listBlobsSegmented().getResults().stream().filter(listBlobItem -> listBlobItem.getUri().toString().contains(subContainer)).findFirst().get()).listBlobsSegmented().getResults().size();
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        } 
    }

}


기존 BLOB 스토리지 계정과 새 BLOB 스토리지 계정의 모든 BLOB를 계산합니다.@gandikota-saikoushik을 기반으로 하는 이 솔루션은 블럽이 매우 많은 블럽 용기에 효과가 있습니다.

//setup set values from Azure Portal
var accountName = "<ACCOUNTNAME>";
var accountKey = "<ACCOUTNKEY>";
var containerName = "<CONTAINTERNAME>";
uristr = $"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey}";

var storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse(uristr);
var client = storageAccount.CreateCloudBlobClient();
var container = client.GetContainerReference(containerName);
BlobContinuationToken continuationToken = new BlobContinuationToken();
blobcount = CountBlobs(container, continuationToken).ConfigureAwait(false).GetAwaiter().GetResult();
Console.WriteLine($"blobcount:{blobcount}");


public static async Task<int> CountBlobs(CloudBlobContainer container, BlobContinuationToken currentToken)
{
    BlobContinuationToken continuationToken = null;
    var result = 0;
    do
    {
        var response = await container.ListBlobsSegmentedAsync(continuationToken);
        continuationToken = response.ContinuationToken;
        result += response.Results.Count();
    }
    while (continuationToken != null);

    return result;
}

List blobs 접근법은 정확하지만 수백만 개의 blobs가 있는 경우 속도가 느립니다.몇 가지 경우 동작하지만 비교적 빠른 다른 방법은MetricsHourPrimaryTransactionsBlob테이블. 계정 수준에서 메트릭이 매시간 집계됩니다.

https://learn.microsoft.com/en-us/azure/storage/common/storage-analytics-metrics

이거 써도 돼

 public static async Task<List<IListBlobItem>> ListBlobsAsync()
 {
   BlobContinuationToken continuationToken = null;
   List<IListBlobItem> results = new List<IListBlobItem>();
   do
    {
      CloudBlobContainer container = GetContainer("containerName");
      
      var response = await container.ListBlobsSegmentedAsync(null,
         true, BlobListingDetails.None, 5000, continuationToken, null, null);
      
      continuationToken = response.ContinuationToken;

      results.AddRange(response.Results);

      } while (continuationToken != null);
       return results;
 }

그리고 나서 전화한다.

var count = await ListBlobsAsync().Count;

도움이 되기를 바라다

언급URL : https://stackoverflow.com/questions/6861865/getting-blob-count-in-an-azure-storage-container

반응형