1

我们在 Azure 表存储中有一个表,自新实施以来,它目前有 50,000 个项目。

PartitionKey:字符串形式的日期时间值
RowKey:字符串形式的数值

我们TableQuery用来生成过滤条件。PartitionKey 过滤器类似于:PartitionKey ge '201801240000000000' && "PartitionKey lt '201806220000000000'"

不幸的是,我们不能使用 RowKey 过滤器,因为我们想要两个日期之间的数据。

要获取大约一个月的数据,大约需要 5 秒。而要获取大约 3 个月的时间,则需要更多的时间。

虽然我们有一个缓存策略,但第一次获取数据需要很长时间。就像数据过滤器在日期发生变化时需要很长时间一样。

任何提高性能的建议将不胜感激。

4

2 回答 2

4

据我从您的帖子中可以看出,您遇到的最大问题是您的查询在一个查询中跨越了多个分区。这对于性能来说不是最佳的。根据下面的列表,您介于Partition ScanTable Scan之间,因为您正在指定分区键,但您正在使用其中的多个。

  • 点查询是最有效的查找,建议用于大容量查找或需要最低延迟的查找。通过指定 PartitionKey 和 RowKey 值,此类查询可以使用索引非常有效地定位单个实体。例如:$filter=(PartitionKey eq 'Sales') 和 (RowKey eq '2')
  • 第二好的是范围查询,它使用 PartitionKey 并过滤一系列 RowKey 值以返回多个实体。PartitionKey 值标识特定分区,RowKey 值标识该分区中实体的子集。例如:$filter=PartitionKey eq 'Sales' and RowKey ge 'S' and RowKey lt 'T'
  • 第三个最好的是分区扫描,它使用 PartitionKey 并过滤另一个非键属性,并且可能返回多个实体。PartitionKey 值标识特定分区,属性值选择该分区中实体的子集。例如:$filter=PartitionKey eq 'Sales' 和 LastName eq 'Smith'
  • 表扫描不包括 PartitionKey 并且效率非常低,因为它会依次搜索构成表的所有分区以查找任何匹配的实体。无论您的过滤器是否使用 RowKey,它都会执行表扫描。例如:$filter=LastName eq 'Jones'
  • 返回多个实体的查询返回按 PartitionKey 和 RowKey 顺序排序的实体。为避免重新使用客户端中的实体,请选择定义最常见排序顺序的 RowKey。

来源:Azure 存储表设计指南:设计可扩展和高性能表

另一篇非常有用的文章是:What PartitionKey and RowKey are for in Windows Azure Table Storage,尤其是当您查看此图像时:

根据分区的大小和负载,分区在机器之间呈扇形分布。每当分区负载过高或大小增加时,Windows Azure 存储管理可以启动并将分区移动到另一台机器: 分区

编辑:
如果您想以多种方式查询数据,请考虑以多种方式存储它们。尤其是因为存储很便宜,所以多次存储数据并没有那么糟糕。这样您就可以优化阅读。这就是所谓的物化视图模式,它可以“帮助支持高效的查询和数据提取,并提高应用程序的性能”。

但是,您应该记住,这对于静态数据来说很简单。如果您的数据变化很大,那么在多次存储时保持它们同步可能会很麻烦。

于 2018-06-27T06:45:38.860 回答
1

rickvdbosch 的回答很到位。

假设这是一个应用程序,这里有一些额外的想法。一种方法是并行读取较小的 PartitionKey 范围。例如,假设正在处理的范围是June/2018,我们将有:

  • Thread-1 => PartitionKey ge '20180601' && PartitionKey lt '20180605'
  • Thread-2 => PartitionKey ge '20180605' && PartitionKey lt '20180610'
  • Thread-3 => PartitionKey ge '20180610' && PartitionKey lt '20180615'
  • Thread-4 => PartitionKey ge '20180615' && PartitionKey lt '20180620'
  • Thread-5 => PartitionKey ge '20180620' && PartitionKey lt '20180725'
  • Thread-6 => PartitionKey ge '20180625' && PartitionKey lt '20180701'

此外,在不使用 TableQuery 结构的情况下,可以更积极地并行读取较小的分区(例如每天)。

请注意,上述两种方法都不能处理高度不平衡的分区策略。例如,假设 2018 年 6 月的 95% 数据存储在“20180605”到“20180610”范围内或在一天内,与串行读入相比,整体执行时间可能会或可能不会有改善这种情况下,特别是因为并行开销(例如线程、内存分配、同步等)。

现在,假设这是在 Windows 操作系统上运行的 .NET 应用程序,并且上述方法对您的场景很有吸引力,请考虑:

  • 增加最大连接数;
  • 禁用 Nagle 算法;

在下面找到代码片段以更改应用程序配置。请注意:

  • 可以为 maxconnection 定义地址(例如https://stackoverflow.com)而不是使用"*"
  • 建议在发布到生产环境之前运行性能测试以对 maxconnection 的适当配置进行基准测试。

在https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/network/connectionmanagement-element-network-settings中查找有关连接管理的更多详细信息。

于 2018-06-29T20:42:38.840 回答