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

时间:2016-11-01 15:41:30

标签: c# .net azure azure-storage azure-table-storage

我在Azure表上有以下查询:

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作为我的连接字符串。我该怎么做才能让它更高效?我所要做的就是计算记录的数量,当然必须有更快的方法吗?

3 个答案:

答案 0 :(得分:2)

您可能已经知道Azure表的LINQ支持有限,目前不支持Count({3}})。

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

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

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

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

答案 1 :(得分:1)

Azure表存储中没有Count功能。您查询中实际发生的事情是,您要撤回所有记录并逐个枚举。

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

表存储是具有聚簇键的键值对存储,由分区键和行键组成。几乎就是这样。如果您需要聚合功能,我建议您查看DocumentDB(尽管它们只实现了一些聚合功能)或SQL Azure。

答案 2 :(得分:1)

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

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

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