如何使用多个PK从Azure表存储中获取多个表实体



我有一堆主键——数以万计,我想检索它们关联的表实体。所有行键都是空字符串。据我所知,最好的方法是逐个异步查询它们。这看起来很快,但理想情况下,我想在一个事务中将几个实体组合在一起。玩新的存储客户端时,我有以下代码失败:

var sample = GetSampleIds(); //10000 pks
var account = GetStorageAccount();
var tableClient = account.CreateCloudTableClient();
var table = tableClient.GetTableReference("myTable");
//I'm trying to get first and second pk in a single request.
var keyA = sample[0];
var keyB = sample[1];
var filterA = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, keyA);
var filterB = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, keyB));
//filterAB = "(PartitionKey eq 'keyA') or (PartitionKey eq 'keyB')"
var filterAB = TableQuery.CombineFilters(filterA, TableOperators.Or, filterB);
var query = new TableQuery<TweetEntity>().Where(filterAB);
//Does something weird. I thought it might be fetching a range at one point.
//Whatever it does it doesn't return. Expected the following line to get an array of 2 items.
table.ExecuteQuery(query).ToArray()
// replacing filterAB in query with either filterA or filterB works as expected

示例总是显示CombineFilters在PK和RK上工作,但这对我来说没有用。我认为这是不可能的。

问题

是否可以通过PK将实体捆绑在一起?我知道过滤器的最大长度是15,但当你获取10000个项目时,即使是2也是一个潜在的改进。此外,手册在哪里?在任何地方都找不到合适的文档。例如,用于CombineFilters的MSDN是intellisense提供的一个基本外壳,它封装了较少的信息。

tl;dr:听起来你需要重新思考你的分区策略。当您通常必须查询或处理多个ID时,唯一的、非顺序的ID不是好的PK。更多:

分区键实际上并不是"主"键。它们更多地被认为是您想要处理的分组的、密切相关的数据集。你可以根据id、日期等进行分组。PK用于扩展系统——理论上,每个PK可以有一个分区服务器处理你的数据。

对于你的问题:做你正在做的事情不会有很好的表现。事实上,OR查询是未优化的,需要进行全表扫描(错误)。因此,您不应该执行PK="foo"或PK="bar",而应该执行2个查询(并行),因为这样可以获得更好的性能。

回到您的核心问题,如果您使用特定实体的唯一标识符并将其描述为PK,那么这也意味着您一次不能处理一个以上的实体。为了处理实体,您确实需要一个公共分区键。你能想出一个更好的来描述你的实体吗?日期/时间有效吗?其他一些共同的属性?这些往往是很好的派对钥匙。您唯一能做的另一件事就是所谓的分区排列——您的查询往往是根据分区键排列的。一个例子是日期时间分区键。您可以使用文件记号来描述您的分区,并以PKs的顺序数据记号结束。然后,您的查询可以使用>和<查询以指定范围(无OR)。这些可以进行更优化,但您仍可能获得大量的延续令牌。

正如dunnry在回复中提到的,这种方法的问题是OR查询非常慢。我遇到了在没有存储客户端的情况下工作的问题(在这一点上,我不确定它出了什么问题,假设它可能是一个错误),但在没有OR查询的情况下分别获得两个实体比使用OR查询获得它们快得多(!)。

最新更新