【发布时间】:2012-05-28 12:33:38
【问题描述】:
我需要通过行键的集合(在一个分区中)来查找多个实体。执行此操作的正确查询是什么?
【问题讨论】:
-
我建议使用任务并行库并单独查询它们。
标签: .net azure azure-storage azure-table-storage
我需要通过行键的集合(在一个分区中)来查找多个实体。执行此操作的正确查询是什么?
【问题讨论】:
标签: .net azure azure-storage azure-table-storage
这取决于您要优化什么。事实证明,指定多个行键,即使它们都在同一个分区中,也会导致分区扫描。查询优化器不足以处理 OR 查询。分区扫描可能需要数十到数百毫秒,具体取决于分区的大小。它总是比点查询慢。
如果您想优化速度,您应该分别执行每个查询。不要使用任务并行库,使用 begin/end 函数,它们的扩展性更好。
如果延迟不是问题,请执行 OR 查询。它会更慢,但它会算作一次交易,因此会更便宜。
【讨论】:
begin 和end 开头的函数:)。它们是老式的异步调用。我有一段时间没有使用这些库了,所以我不知道它们是否仍然相关 - 它们可能已被 Async-style Task 返回函数所取代。此外,查询优化器可能在过去近 5 年中变得更好。
仅通过 rowkey 查询的问题(我正在解释要暗示的原始问题):您最终会进行表扫描,因为该 rowkey 可能存在于任何分区中。而且,如果您单独执行这些查询,您最终会为每个查询进行表扫描(即使使用任务并行库,正如@GlennFerrieLive 在对原始问题的评论中所建议的那样)。
您可以使用$filter(如this article 中所述)或离散的行键列表(过滤器内限制为 15 个单独的比较)指定行键的范围。最终应该只进行一次表扫描,但仍然...进行表扫描。
如果可以在查询中指定分区键,您应该这样做,因为它会使您的查询返回得更快。好的,快得多是相对的,因为我不知道您存储的数据量。
编辑:每次通过评论更新,因为您知道 partitionkey,您可以按照上面的指导在单个过滤器中指定行键范围或离散行键。或者...如果您有更多的行键,您可以考虑通过 TPL 执行这些(考虑到没有表扫描,现在这很有意义),或者作为每个过滤器的单个行键,或者分组到范围或过滤列表中。
【讨论】:
您可以在运行时创建过滤器字符串,并在异步情况下运行 ExecuteQuery 或 ExecuteQuerySegmentedAsync。例如在 C# 中:
string queryFilter = $"(PartitionKey eq '{<PK name>}') and" +
$"({string.Join(" or", <YOUR LIST>.Select(tl => $"(RowKey eq '{<the property>}')"))})";
var query = new TableQuery<ExternalTranslationEntity>().Where(queryFilter).Take(<e.g yourList>.Count).
Select(new List<string> { nameof(<if you want specific columns>) });
TableContinuationToken? token = null;
do
{
var segment = await _translationsTable.ExecuteQuerySegmentedAsync(query, token);
if (segment.Results.Any())
{
segment.Results.ForEach(r =>
{
//do whaterver you want
});
}
token = segment.ContinuationToken;
} while (token != null);
【讨论】: