我使用以下逻辑查询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;
当我指向我的开发ATS时,这似乎在合理的时间内返回,但是当我指向包含数百万个分区的产品ATS时,需要花费很长时间。我的问题是,有什么方法可以更有效地查询ATS吗?
我的查询不一定需要在分区键中获取所有行键。我只需要它们的一部分。
答案 0 :(得分:0)
表中的分区数量在性能方面不应该是个问题。但是,分区中的行数是个问题。
<强>问题:强>
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
是您在本地过滤掉不需要的行的自定义方法。这将允许不需要的行被垃圾收集并减少内存压力(尽管不能消除它)。