Kur*_*ula 6 c# azure azure-storage azure-table-storage azure-sql-database
我使用Azure表存储来通过时间戳过滤器检索数据.我发现执行速度非常慢,因为时间戳不是分区键或行键.我研究了stackoverflow,发现时间戳应该转换为ticks并存储到Partition键中.我做了同样的事情,在插入数据时我采用了下面的字符串并将tick字符串插入分区键.
string currentDateTimeTick = ConvertDateTimeToTicks(DateTime.Now.ToUniversalTime()).ToString();
public static long ConvertDateTimeToTicks(DateTime dtInput)
{
long ticks = 0;
ticks = dtInput.Ticks;
return ticks;
}
Run Code Online (Sandbox Code Playgroud)
这很好,直到这里.但是当我尝试检索最近5天的数据时,我无法查询对分区键的勾选.我想获取最近5天的数据.我在下面的代码中犯了什么错误?
int days = 5;
TableQuery<MyEntity> query = new TableQuery<MyEntity>()
.Where(TableQuery.GenerateFilterConditionForDate("PartitionKey", QueryComparisons.GreaterThanOrEqual, "0"+DateTimeOffset.Now.AddDays(days).Date.Ticks));
Run Code Online (Sandbox Code Playgroud)
Mar*_*age 10
您确定要使用刻度线作为分区键吗?这意味着每个可测量的100 ns瞬间变为它自己的分区.使用基于时间的数据,您可以使用分区键指定每小时,分钟或甚至秒的间隔,然后指定具有实际时间戳的行键.
抛开这个问题让我告诉你如何进行查询.首先让我评论一下如何生成分区键.我建议你这样做:
var partitionKey = DateTime.UtcNow.Ticks.ToString("D18");
Run Code Online (Sandbox Code Playgroud)
不要DateTime.Now.ToUniversalTime()
用来获取当前的UTC时间.它将在内部使用DateTime.UtcNow
,然后将其转换为本地时区,ToUniversalTime()
并将转换回UTC,这只是浪费(并且比您想象的更耗时).
并且您的ConvertDateTimeToTicks()
方法除了获取Ticks
属性之外没有任何其他目的,因此它只是使您的代码更复杂而不添加任何值.
以下是执行查询的方法:
var days = 5;
var partitionKey = DateTime.UtcNow.AddDays(-days).Ticks.ToString("D18")
var query = new TableQuery<MyEntity>().Where(
TableQuery.GenerateFilterCondition(
"PartitionKey",
QueryComparisons.GreaterThanOrEqual,
partitionKey
)
);
Run Code Online (Sandbox Code Playgroud)
分区键的格式为18个字符的字符串,允许您使用简单的比较.
我建议您移动代码以生成分区键(和行键)到函数中,以确保在整个代码中以相同的方式生成键.
使用18个字符的原因是因为今天以及未来几千年的Ticks
值DateTime
使用18位十进制数字.如果您决定将分区键基于小时,分钟或秒,而不是100 ns,那么您可以相应地缩短分区键的长度.
正如Martin建议的那样,使用时间戳作为分区键几乎肯定不是你想要做的.
分区是Azure表存储中的比例单位,或多或少表示数据的物理分段.它们是一种可扩展性优化,允许您"存储硬件"以解决存储越来越多数据的问题,同时保持可接受的响应时间(传统上在数据存储中很难).您可以通过为每行分配分区键来定义数据中的分区.几乎不可取的是每一行都存在于自己的分区中.
在ATS中,行键成为给定分区中的唯一键.因此,分区键+行键的组合是整个ATS表中的真正唯一键.
有很多建议可以选择有效的分区键和行键......其中没有一个是通用的.这取决于您的数据的性质,您预期的查询模式等.
选择一个分区键,将您的数据聚合成一组分布均匀的"桶".在所有条件相同的情况下,如果你预计你的表中有100万行,那么拥有10个每行100,000行的桶通常很有用......或者可能有100个桶,每行10,000行.在查询时,您需要选择要查询的分区,因此桶的数量可能对您很重要."桶"通常对应于您域中的自然分段概念...代表每个美国州的桶,或代表公司中每个部门的桶等.请注意,没有必要(或通常可能)完美分布式水桶...尽可能接近,尽力而为.
您可能故意分配不均匀分布的一个示例是,如果您打算通过存储桶改变查询模式...存储桶A将接收大量廉价,快速查询,存储桶B更少,更昂贵的查询等.或者可能存储桶A数据当存储桶B数据频繁更改时,它将保持静态 这也可以通过多个表来实现......所以没有"一刀切"的答案.
鉴于我们对您的问题知识有限,我喜欢Martin建议使用时间跨度作为您的分区键.小跨度将导致许多分区,并且(除其他外)使得利用多个时间跨度的查询相对昂贵.较大的跨度将导致跨越跨越的聚合成本更少,但是将导致更大的分区,从而导致分区内更昂贵的查询(它还将使识别合适的行键更具挑战性).
最终,您可能需要尝试一些选项来找到最适合您的数据和预期查询的选项.
另外一条建议......不要害怕考虑在多个数据存储中复制数据以适应各种各样的查询类型.并非每个查询都能有效地针对单个架构或存储配置.跨商店同步数据所需的工作量可能小于您的意愿所需的弯曲查询技术X.
祝你好运!