【问题标题】:Query Azure Table Storage efficiently?高效查询 Azure 表存储?
【发布时间】:2017-06-21 17:50:39
【问题描述】:

我正在使用以下逻辑查询 ATS:

var query = from m in context.CreateQuery<MyTable>(tableName)
            where m.PartitionKey.CompareTo(partitionKey) == 0  
            select m;

var results = new List<MyTable>();

CloudTableQuery<MyTable> messageTableQuery = (CloudTableQuery<MyTable>)query.AsTableServiceQuery();
ResultContinuation rc = null;

do
{
    var asyncResult = rc == null ? messageTableQuery.BeginExecuteSegmented(null, null) :
        messageTableQuery.BeginExecuteSegmented(rc, null, null);
    ResultSegment<MyTable> result = messageTableQuery.EndExecuteSegmented(asyncResult);
    results.AddRange(result.Results);
    rc = result.ContinuationToken;
} while (rc != null);

return results;

当我指向我的 dev ATS 时,这似乎会在合理的时间内返回,但是当我指向包含数百万个分区的 prod ATS 时,这需要很长的时间。我的问题是,有什么方法可以更有效地查询 ATS?

我的查询不一定需要获取分区键中的所有行键。我只需要其中的一部分。

【问题讨论】:

  • 从上面的代码中不清楚您正在执行的查询是否包含PartitionKey。为获得最佳性能,您的查询必须包含 PartitionKey。
  • 嗨 Gaurav,我已将查询添加到问题中。
  • 如果您知道选择行的任何特定标准,例如按时间戳过滤,则可以添加过滤器。并不是说它会有很大的不同,Partitionkey.compareto 可以更改为 == 。 compareto 主要在需要排序时使用。
  • 我知道我想从 ATS 获取的行键列表,但它们不符合条件。它们只是指南的列表。查询 ATS 以获取完整分区并在客户端进行过滤是否更快,或者迭代查询 ATS 以获取 PartionKey==x && RowKey==y 更快?

标签: azure storage


【解决方案1】:

表中的分区数量在性能方面应该不是问题。但是,分区中的行数是个问题。

问题:

1) 如果 PartitionKey = 0 的分区中有很多行,那么使用当前查询,您将检索 1000 行分段中的每一行,然后在本地对其进行过滤。因此,如果您的分区中有 100,000 行,则代码将进行 100 次查询。每个响应可能很大并且包含许多您不需要的行。

2) 内存压力。您可能遇到的另一个问题是通过下载所有行并将它们放在一个列表中来破坏本地​​内存。

解决方案:

1) 如果您知道需要检索的所有 RowKey GUID,则可以创建更高效​​的查询(取决于您需要多少行):

from m in context.CreateQuery<MyTable>(tableName) where m.PartitionKey.CompareTo(partitionKey) == 0 && (m.RowKey.CompareTo(guid1) == 0 || m.RowKey.CompareTo(guid2) == 0 ... ) select m;

如果您有很多行要检索,您最终可能会达到查询允许的最大长度。这意味着您需要分块您的 GUID 列表,并为每个块发送单独的请求。

此外,您可能会发现使用表过滤器(TableQuery.GenerateFilterCondition 和 TableQuery.CombineFilters)更容易构建查询,如下所述:Querying Windows Azure Table Storage with multiple query criteria

2) 如果解决方案 1 不适用于您的问题,并且您需要在本地进行过滤,则在检索每个细分时进行过滤。

do { ... var filteredResults = FilterResultsByGuid(result.Results); // Imp results.AddRange(filteredResults); ... } while (rc != null);

FilterResultsByGuid 是您在本地过滤掉不需要的行的自定义方法。这将允许对不需要的行进行垃圾收集并减少内存压力(尽管不能消除它)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2015-03-16
    • 2021-12-14
    • 2016-08-05
    • 1970-01-01
    相关资源
    最近更新 更多