问题 不支持使用TableBatchOperation检索多行?
下面是一段初始化TableBatchOperation的代码,用于在一个批处理中检索两行:
TableBatchOperation batch = new TableBatchOperation();
batch.Add(TableOperation.Retrieve("somePartition", "rowKey1"));
batch.Add(TableOperation.Retrieve("somePartition", "rowKey2"));
//second call throws an ArgumentException:
//"A batch transaction with a retrieve operation cannot contain
//any other operation"
如上所述,抛出异常,似乎 不支持在单个批次中检索N行。
这对我来说很重要,因为我需要为每个请求检索大约50行。 这个问题与成本明智一样明显。 您可能知道,Azure表存储定价基于事务量,这意味着50个检索操作比单个批处理操作贵50倍。
我错过了什么吗?
边注
我正在使用新的Azure Storage api 2.0。
我注意到这个问题从未在网上提出过。最近可能添加了这个约束吗?
编辑
我在这里找到了一个相关问题: PartitionKey / RowKey列表上的Azure表存储查询速度非常慢。
似乎在rowkeys上使用带有“或”的TableQuery会产生全表扫描。
这里真的是一个严重的问题......
7722
2018-01-06 04:24
起源
答案:
在Azure表存储(ATS)中设计分区密钥(PK)和行密钥(RK)方案时,您应首先考虑如何检索数据。正如你所说的那样,你运行的每个查询都需要花钱,但更重要的是时间,所以你需要在一个有效的查询中获得所有数据。您可以在ATS上运行的高效查询具有以下类型:
- 确切的PK和RK
- 精确PK,RK范围
- PK范围
- PK范围,RK范围
根据你的评论我猜你有一些类似的数据:
PK RK Data
Guid1 A {Data:{...}, RelatedRows: [{PK:"Guid2", RK:"B"}, {PK:"Guid3", RK:"C"}]}
Guid2 B {Data:{...}, RelatedRows: [{PK:"Guid1", RK:"A"}]
Guid3 C {Data:{...}, RelatedRows: [{PK:"Guid1", RK:"A"}];}
你已经在Guid1上检索了数据,现在你需要加载Guid2和Guid3。我也假设这些行没有共同点,就像它们都是同一个用户一样。考虑到这一点,我会创建一个额外的“索引表”,它看起来像这样:
PK RK Data
Guid1-A Guid2-B {Data:{....}}
Guid1-A Guid3-C {Data:{....}}
Guid2-B Guid1-A {Data:{....}}
Guid2-B Guid1-A {Data:{....}}
其中PK是父亲的组合PK和RK,而RK是子行的组合PK和RK。然后,您可以运行一个查询,该查询返回PK =“Guid1-A”的所有行,您只需一次调用(或整个调用两次)即可获得所有相关数据。这产生的最大开销是在你的写入中,所以现在当你正确行时,你还必须为每个相关行写入行,并确保数据保持最新(这可能不是问题对于你,如果这是一种写一种情况)。
如果我的任何假设是错误的,或者如果您有一些示例数据,我可以使用更相关的示例更新此答案。
5
2018-01-08 03:33
尝试这样的事情:
TableQuery<DynamicTableEntity> query = new TableQuery<DynamicTableEntity>()
.Where(TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "partition1"),
TableOperators.And,
TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "row1"),
TableOperators.Or,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "row2"))));
4
2017-09-16 20:55
我知道这是一个老问题,但由于Azure STILL不支持二级索引,它似乎有一段时间是相关的。
我遇到了同样的问题。在我的场景中,我需要在同一个分区中查找数百个项目,其中有数百万行(想象GUID为行键)。我测试了几个选项来查找10,000行
- (PK && RK)
- (PK && RK1)|| (PK&RK2)|| ...
- PK &&(RK1 || RK2 || ...)
我使用的是异步API,最大并行度为10度(最多10个未完成请求)。我还测试了几种不同的批量(10行,50,100)。
Test Batch Size API calls Elapsed (sec)
(PK && RK) 1 10000 95.76
(PK && RK1) || (PK && RK2) 10 1000 25.94
(PK && RK1) || (PK && RK2) 50 200 18.35
(PK && RK1) || (PK && RK2) 100 100 17.38
PK && (RK1 || RK2 || … ) 10 1000 24.55
PK && (RK1 || RK2 || … ) 50 200 14.90
PK && (RK1 || RK2 || … ) 100 100 13.43
注意:这些都在同一个分区内 - 只有多个rowkeys。
我很乐意减少API调用的数量。但是作为一个额外的好处,经过的时间也明显减少了,节省了计算成本(至少在我的最后!)。
不足为奇的是,100行的批次提供了最佳的流逝性能。显然还有其他性能方面的考虑,特别是网络使用(例如,#1几乎不使用网络,而其他人则更难推动)
编辑
查询许多rowkeys时要小心。 (或当然)查询的URL长度限制。如果超过长度,查询仍将成功,因为该服务无法判断URL是否被截断。在我们的例子中,我们将组合查询长度限制为大约2500个字符(URL编码!)
3
2018-05-29 19:08
Azure表存储不支持批处理“获取”操作。支持的操作包括:添加,删除,更新和合并。您需要将查询作为单独的请求执行。为了加快处理速度,您可能希望并行执行这些查询。
0
2018-01-06 06:29
您最好的办法是创建一个Linq / OData选择查询...它将获取您正在寻找的内容。
为了获得更好的性能,您应该为每个分区进行一次查询并同时运行这些查
我没有亲自测试过,但认为它会起作用。
0
2018-01-07 13:13
每个分区有多少个实体?通过一次检索操作,您可以为每个查询提取最多1000条记录。然后,您可以对内存集进行行密钥过滤,只需支付1次操作。
另一种选择是做一个 行键范围查询 在一个操作中检索部分分区。基本上,您指定要返回的行键的上限和下限,而不是整个分区。
0
2018-01-07 13:59
好的,所以批处理检索操作,最好的情况是表查询。不太理想的情况需要并行检索操作。
根据您的PK,RK设计,您可以基于(PK,RK)列表找出您需要执行的最小/最有效的检索/查询操作集。然后,您可以并行获取所有这些内容并整理出客户端的确切答案。
IMAO,这是微软设计小姐添加的 Retrieve
方法 TableBatchOperation
class,因为它传达了表存储API不支持的语义。
现在,我不想写一些超级高效的东西,所以我只想在这里留下这个超级简单的解决方案。
var retrieveTasks = new List<Task<TableResult>>();
foreach (var item in list)
{
retrieveTasks.Add(table.ExecuteAsync(TableOperation.Retrieve(item.pk, item.rk)));
}
var retrieveResults = new List<TableResult>();
foreach (var retrieveTask in retrieveTasks)
{
retrieveResults.Add(await retrieveTask);
}
这个异步代码块将获取实体 list
并行并将结果存储在 retrieveResults
保留订单。如果您需要获取连续的实体范围,则可以使用范围查询来改善这一点。
有一个最佳点(通过测试你必须找到)是查询更多实体的速度可能比特定批次检索所需的更快/更便宜,然后丢弃您不需要的检索结果。
如果你有一个小分区,你可能会受益于这样的查询:
where pk=partition1 and (rk=rk1 or rk=rk2 or rk=rk3)
如果您的密钥之间的字典(即排序顺序)距离很长,您可能希望并行获取它们。例如,如果将字母存储在表存储中,则获取 a
和 z
相距很远最好是在获取时进行并行检索操作 a
, b
和 c
最接近的是查询。取 a
, b
c
,和 z
将受益于混合方法。
如果您事先了解所有这些,您可以计算出给定一组PK和RK最好的事情。您对基础数据的排序方式了解得越多,结果就越好。我建议对此进行一般性处理,然后尝试应用您从这些不同查询模式中学到的知识来解决您的问题。
0
2018-01-30 18:22