提高此 Azure table 行计数查询的性能

Improving performance of this Azure table row count query

我在 Azure table 上有以下查询:

var count = table.ExecuteQuery(new TableQuery<MessageEntity>()).Count();

这是MessageEntity:

public class MessageEntity : TableEntity
{
    public MessageEntity() { }

    public string Message { get; set; }
}

这个查询真的很慢。在我的开发机器上计算总共 85,000 条记录大约需要 15 秒。我使用 Azure Storage EmulatorUseDevelopmentStorage=true 作为我的连接字符串。我该怎么做才能使其性能更高?我只想统计记录的数量,一定有更快的方法吧?

Azure Table 存储中没有计数功能。在您的查询中实际发生的是您撤回所有记录并逐一枚举它们。

您可以使用一个选项,但我在此建议的任何内容都不会利用内置功能。您可以自己维护一个计数器,但是您必须确保在 上以原子方式写入主 table 仅 写入和删除 你的柜台。你可以看到这很容易出错。

Table Storage是一个键值对存储,有一个聚集键,由Partition Key和Row Key组成。差不多就是这样。如果您需要聚合功能,我建议您查看 DocumentDB(尽管它们只实现了一些聚合功能)或 SQL Azure。

您可能已经知道 Azure 表对 LINQ 的支持有限,目前不支持 Count (List of supported LINQ operators)。

var count = table.ExecuteQuery(new TableQuery<MessageEntity>()).Count();

上面的代码正在从 table 中获取所有实体(一次最多 1000 个实体)并且因为您的 table 中有 20000 个实体,它至少发出 20 个请求天蓝色表。由于每个请求都是对 Azure Tables REST API 的 HTTP 请求,这就是您看到它花费如此多时间的原因。当您尝试从真实存储帐户中获取 table 中实体的计数时,情况会变得更糟。

一种可以减少时间的方法是减少通过网络传输的数据(尤其是响应数据)。目前,实体的每个 属性 都作为响应数据的一部分返回。由于您只对总数感兴趣,因此您可以使用 Query Projection 并只得到一个 属性(比如 PartitionKeyRowKey)作为响应。这样您的响应数据将比您当前拥有的数据小很多,并且应该会减少一些时间。

如果知道计数对您来说真的很重要,您可以做的另一件事是通过一些后台进程计算计数并在单独的 table 中更新它。

以下是如何在不检索实体的情况下获取 Azure table 中单个分区的实体数。对于每个分区,创建一个额外的实体,我们称之为行计数实体,具有相同的分区键但行键不变(即 "rowcountRK")。行计数实体将具有单个长类型 属性 即。 "rowCount" 这将保留该分区的行数。

每次您向该分区插入一个实体时,您还会增加该分区的行计数实体的 rowCount 属性。您可以在批处理操作中执行此操作。 Azure table 批处理操作在同一个分区内是原子的,因此不会有任何不一致。同样,每次从分区中删除一个实体时,您也会减少行计数实体的 rowCount 属性,并再次将这些操作在批处理操作中发送到 azure table 存储以实现一致性和原子性。

现在,如果您想查询单个分区中的行数,您需要做的就是查询该分区的行计数实体,而无需 retrieve/scan 任何其他操作。如果您想获得整个 table 中的总行数,假设您的 table 中有多个分区,那么您需要查询 [=19] 中的所有行计数实体=] 并在客户端对它们的行计数 属性 值求和。这将导致 table 扫描,但负载会更小,它也可能比扫描整个 table 更快。或者,如果您知道您的分区键,那么您可以对每个分区的行计数实体进行并发点查询并将它们相加,这很可能比整个 table 扫描更有效。