我需要通过行键的集合(在一个分区中)来查找多个实体。什么是正确的查询?
3 回答
这取决于您要优化的内容。事实证明,指定多个行键,即使它们都在同一个分区中,也会导致分区扫描。查询优化器不足以处理 OR 查询。分区扫描可能需要数十到数百毫秒,具体取决于分区的大小。它总是比点查询慢。
如果您想优化速度,您应该分别执行每个查询。不要使用任务并行库,使用开始/结束函数,它们可以更好地扩展。
如果延迟不是问题,请执行 OR 查询。它会更慢,但它会算作一次交易,所以它会更便宜。
仅通过行键查询的问题(我正在解释要暗示的原始问题):您最终将进行表扫描,因为该行键可能存在于任何分区中。而且,如果您单独执行这些查询,您最终会为每个查询进行表扫描(即使使用任务并行库,正如@GlennFerrieLive 在对原始问题的评论中所建议的那样)。
您可以使用$filter
(如本文所述)或离散的行键列表(过滤器中限制为 15 个单独的比较)指定行键的范围。这应该只以一次表扫描结束,但仍然......表扫描。
如果可以在查询中指定分区键,您应该这样做,因为它会使您的查询返回得更快。好的,更快是相对的,因为我不知道您存储的数据量。
编辑:每次通过评论更新,因为您知道分区键,您可以按照上面的指导在单个过滤器中指定行键范围或离散行键。或者...如果您有更多的行键,您可以考虑通过 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);