我有一个Azure表,客户发布消息,单个表中可能有数百万条消息。我想找到最快的方式来获取最近10分钟内发布的消息(这是我刷新网页的频率)。由于只对分区键编制索引,因此我使用了日期&消息作为分区键发布的时间,例如字符串作为ISO8601日期格式,如“2009-06-15T13:45:30.0900000”
伪代码示例:
var message = "Hello word!";
var messagePartitionKey = DateTime.Now.ToString("o");
var messageEntity = new MessageEntity(messagePartitionKey, message);
dataSource.Insert(messageEntity);
,然后查询过去10分钟内发布的消息,如下所示(未经测试的伪代码):
// Get the date and time 10 minutes ago
var tenMinutesAgo = DateTime.Now.Subtract(new TimeSpan(0, 10, 0)).ToString("o");
// Query for the latest messages
var latestMessages = (from t in
context.Messages
where t.PartitionKey.CompareTo(tenMinutesAgo) <= 0
select t
)
但指数会好转吗?或者它会导致全表扫描?有人有更好的想法吗?我知道每个表项都有一个时间戳,但它没有编入索引,所以它对我来说太慢了。
答案 0 :(得分:5)
我认为你有正确的基本想法。您设计的查询应该尽可能高效。但是我可以提供一些改进。
使用DateTime.Now
而不是Date.UtcNow
。根据我的理解实例设置为使用Utc时间作为他们的基础,但这只是确保你将苹果与苹果进行比较,并且你可以可靠地将时间转换回你想要的任何时区显示它们。
不是将时间存储为.ToString("o")
而是将时间转换为刻度并存储,最终会减少格式化问题(有时候你会得到最终的时区规范,有时候不会)。此外,如果您总是希望看到从最近到最旧排序的这些消息,您可以从最大刻度数中减去刻度数,例如
var messagePartitionKey = (DateTime.MaxValue.Ticks - _contactDate.Ticks).ToString("d19");
指定行键也是一个好主意。虽然两个消息极不可能在完全相同的时间发布,但这并非不可能。如果您没有明显的行键,则只需将其设置为Guid。
答案 1 :(得分:4)
Table的主键是PartitionKey和RowKey(形成聚簇索引)的组合。
在你的情况下,只需使用RowKey而不是ParitionKey(为此提供一个常量值)。
您还可以按照诊断方法,例如每隔十分钟创建一个新的分区键。但这种方法主要用于诸如Archieving / Purging等的要求,
答案 2 :(得分:3)
我建议做类似于Diagnostics API与WADPerformanceCountersTable一样的操作。 PartitionKey将多个时间戳分组到一个项目中。即:它将所有时间戳舍入到最接近的几分钟(比如,最近的5分钟)。这样,您就没有有限数量的分区键,但仍然能够对它们进行远程查询。
因此,例如,您可以拥有一个映射到每个时间戳的PartitionKey,该时间戳四舍五入为00:00,00:05,00:10,00:15等等,然后转换为Ticks
答案 3 :(得分:0)