Azure Blob C# 客户端 - 使用多个过滤器服务器端
Azure Blobs C# client - using multiple filters server side
我正在尝试加载 blob 名称以在我的程序中进行过滤,然后在应用所有过滤器后我计划下载并处理每个 blob。
目前我们有大约 3 万个 blob 存储在容器中,如下所示:
year/month/day/hour/file.csv(或 file.json 对于未处理的文件)
我的程序需要动态输入开始和结束日期(最长 30 天)以供下载。使用 Azure.Storage.Blobs.BlobContainerItem 和方法 GetBlobs 允许我使用单个字符串前缀进行服务器端过滤。
如果我的日期是 2020/06/01 和 2020/06/02,程序运行速度非常快,大约需要 2 秒来获取 blob 并对其应用其余过滤器。但是,如果我有 2020/05/30 和 2020/06/01,那么我无法输入月份前缀,因为它只需要 1 个字符串,所以我的前缀将只是 2020,这大约需要 15 秒才能完成。其余的过滤在本地完成,但最大的延迟是 GetBlobs() 函数。
有没有其他方法可以从 .NETCore 应用程序使用多个过滤器服务器端?
相关函数如下:
BlobContainerClient container = new BlobContainerClient(resourceGroup.Blob, resourceGroup.BlobContainer);
var blobs = container.GetBlobs(prefix : CreateBlobPrefix(start, end))
.Select(item=> item.Name)
.ToList();
blobs = FilterBlobList(blobs, filter, start, end);
private string CreateBlobPrefix(DateTime start, DateTime end)
{
string prefix = null;
bool sameYear = start.Year == end.Year;
bool sameMonth = start.Month == end.Month;
bool sameDay = start.Day == end.Day;
if (sameYear)
{
prefix = start.Year.ToString();
if (sameMonth)
{
if(start.Month<10)
prefix += "/0" + start.Month.ToString();
else
prefix += "/" + start.Month.ToString();
if (sameDay)
if(start.Day<10)
prefix += "/0" + start.Day.ToString();
else
prefix += "/" + start.Day.ToString();
}
}
return prefix;
编辑:这是我最后的做法。因为使用更好的指定前缀发出多个请求会更快,所以我做了以下操作:
- 在选定时间创建不同日期的列表window(来自 UI 用户输入任何 window 的应用程序)
- 对于创建的每个前缀,我将请求发送到 Azure 以获取 blob
- 将所有 blob 名称连接到 1 个列表中
- 通过为每个 blob 名称使用 blob 客户端来处理列表
代码如下:
foreach (var blobPrefix in CreateBlobPrefix(start, end))
{
var currentList = container.GetBlobs(prefix: blobPrefix)
.Select(item => item.Name)
.ToList();
blobs = blobs.Concat(currentList).ToList();
}
您可以过滤多次,找到日期之间的共同点:
首先使用开始月份和年份 2020/05 的字符串前缀进行过滤,然后在本地进行精确日期过滤。
然后您可以逐渐增加 day/month 过滤器,直到达到范围的末尾。
步进的粒度实际上取决于为给定的平均结果数调用 Azure 所花费的时间。
另一个优点是您可以 运行 这些子查询并行。
我用过这个代码:
var prefixDateFilters = Enumerable.Range(0, 1 + endDateInclusive.Subtract(startDateInclusive).Days)
.Select(offset => startDateInclusive.AddDays(offset))
.Select(date => $"{date.ToString(BlobFileDateTimeFormat)}").ToList();
prefixFilters.AsParallel()
.Select(filter => containerClient.GetBlobs(prefix: filter))
我正在尝试加载 blob 名称以在我的程序中进行过滤,然后在应用所有过滤器后我计划下载并处理每个 blob。 目前我们有大约 3 万个 blob 存储在容器中,如下所示: year/month/day/hour/file.csv(或 file.json 对于未处理的文件)
我的程序需要动态输入开始和结束日期(最长 30 天)以供下载。使用 Azure.Storage.Blobs.BlobContainerItem 和方法 GetBlobs 允许我使用单个字符串前缀进行服务器端过滤。
如果我的日期是 2020/06/01 和 2020/06/02,程序运行速度非常快,大约需要 2 秒来获取 blob 并对其应用其余过滤器。但是,如果我有 2020/05/30 和 2020/06/01,那么我无法输入月份前缀,因为它只需要 1 个字符串,所以我的前缀将只是 2020,这大约需要 15 秒才能完成。其余的过滤在本地完成,但最大的延迟是 GetBlobs() 函数。
有没有其他方法可以从 .NETCore 应用程序使用多个过滤器服务器端?
相关函数如下:
BlobContainerClient container = new BlobContainerClient(resourceGroup.Blob, resourceGroup.BlobContainer);
var blobs = container.GetBlobs(prefix : CreateBlobPrefix(start, end))
.Select(item=> item.Name)
.ToList();
blobs = FilterBlobList(blobs, filter, start, end);
private string CreateBlobPrefix(DateTime start, DateTime end)
{
string prefix = null;
bool sameYear = start.Year == end.Year;
bool sameMonth = start.Month == end.Month;
bool sameDay = start.Day == end.Day;
if (sameYear)
{
prefix = start.Year.ToString();
if (sameMonth)
{
if(start.Month<10)
prefix += "/0" + start.Month.ToString();
else
prefix += "/" + start.Month.ToString();
if (sameDay)
if(start.Day<10)
prefix += "/0" + start.Day.ToString();
else
prefix += "/" + start.Day.ToString();
}
}
return prefix;
编辑:这是我最后的做法。因为使用更好的指定前缀发出多个请求会更快,所以我做了以下操作:
- 在选定时间创建不同日期的列表window(来自 UI 用户输入任何 window 的应用程序)
- 对于创建的每个前缀,我将请求发送到 Azure 以获取 blob
- 将所有 blob 名称连接到 1 个列表中
- 通过为每个 blob 名称使用 blob 客户端来处理列表
代码如下:
foreach (var blobPrefix in CreateBlobPrefix(start, end))
{
var currentList = container.GetBlobs(prefix: blobPrefix)
.Select(item => item.Name)
.ToList();
blobs = blobs.Concat(currentList).ToList();
}
您可以过滤多次,找到日期之间的共同点:
首先使用开始月份和年份 2020/05 的字符串前缀进行过滤,然后在本地进行精确日期过滤。
然后您可以逐渐增加 day/month 过滤器,直到达到范围的末尾。
步进的粒度实际上取决于为给定的平均结果数调用 Azure 所花费的时间。 另一个优点是您可以 运行 这些子查询并行。
我用过这个代码:
var prefixDateFilters = Enumerable.Range(0, 1 + endDateInclusive.Subtract(startDateInclusive).Days)
.Select(offset => startDateInclusive.AddDays(offset))
.Select(date => $"{date.ToString(BlobFileDateTimeFormat)}").ToList();
prefixFilters.AsParallel()
.Select(filter => containerClient.GetBlobs(prefix: filter))