我有一个用作事件日志的 Azure 表。我需要最有效的方法来读取表格底部以检索最新条目。
这样做最有效的方法是什么?
首先,我真的建议您将分区键基于 UTC 刻度。您可以通过将所有的反义词从最新到最旧排序的方式来执行此操作。
然后,如果您想获取 100 条最新日志,您只需调用(可以说查询是来自您最喜欢的客户端的 IQueryable 内容 - 我们使用 Lucifure Stash): query.Take(100);
如果您想在特定时间段内获取实体,请编写: query.Where(x => x.PartitionKey <= value); 或类似的东西。
必须根据构造分区键值的方式构造“值”变量。
假设您要获取最近 15 分钟的数据,请尝试以下伪代码:
DateTime toDateTime = DateTime.UtcNow;
DateTime fromDateTime = toDateTime.AddMinutes(-15);
string myPartitionKeyFrom = fromDateTime.ToString("yy-MM");
string myPartitionKeyTo = toDateTime.ToString("yy-MM");
string query = "";
if (myPartitionKeyFrom.Equals(myPartitionKeyTo))//In case both time periods fall in same month, then we can directly hit that partition.
{
query += "(PartitionKey eq '" + myPartitionKeyFrom + "') ";
}
else // Otherwise we would need to do a greater than and lesser than stuff.
{
query += "(PartitionKey ge '" + myPartitionKeyFrom + "' and PartitionKey le '" + myPartitionKeyTo + "') ";
}
query += "and (RowKey ge '" + fromDateTime.ToString() + "' and RowKey le '" + toDateTime.ToString() + "')";
如果要获取最新的“n”个条目,则需要稍微修改 PartitionKey 和 RowKey 值,以便将最新的条目推送到表的顶部。
为此,您需要使用DateTime.MaxValue.Subtract(DateTime.UtcNow).Ticks;
而不是 DateTime.UtcNow 来计算这两个键。
Microsoft 提供了一个SemanticLogging框架,该框架有一个特定的接收器来记录到 Azure Table。
如果您查看库代码,它会根据 Datetime 生成一个分区键(以相反的顺序):
static string GeneratePartitionKeyReversed(DateTime dateTime)
{
dateTime = dateTime.AddMinutes(-1.0);
return GetTicksReversed(
new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0));
}
static string GetTicksReversed(DateTime dateTime)
{
return (DateTime.MaxValue - dateTime.ToUniversalTime())
.Ticks.ToString("d19", (IFormatProvider)CultureInfo.InvariantCulture);
}
因此,您可以在应用程序中实现相同的逻辑来构建您的分区键。
如果要检索特定日期范围的日志,可以编写如下查询:
var minDate = GeneratePartitionKeyReversed(DateTime.UtcNow.AddHours(-2));
var maxDate = GeneratePartitionKeyReversed(DateTime.UtcNow.AddHours(-1));
// Get the cloud table
var cloudTable = GetCloudTable();
// Build the query
IQueryable<DynamicTableEntity> query = cloudTable.CreateQuery<DynamicTableEntity>();
// condition for max date
query = query.Where(a => string.Compare(a.PartitionKey, maxDate,
StringComparison.Ordinal) >= 0);
// condition for min date
query = query.Where(a => string.Compare(a.PartitionKey, minDate,
StringComparison.Ordinal) <= 0);3