我想使用DynamoDB存储历史收盘价。
我的商店将有少量存货,随着需求的变化,存货也将增加。
我以为我会有一个表,其中唯一的键是"DATE"
,格式为YYYY-MM-DD
。
这意味着表中的每个项目都将具有一个date
键和几个{ TICKER = CLOSING_VALUE }
形式的属性
给定日期的查询也将按所需股票行情的子集进行过滤,例如["INTC", "AAPL"]
。
我有点困惑,因为这个键既可以用作分区键又可以用作排序键。
如何查询给定日期范围内的股票报价器的子集?
更新:
我正在使用...创建表
{
AttributeDefinitions: [
{
AttributeName: Date,
AttributeType: S
}
],
TableName: "Historic",
KeySchema: [
{
AttributeName: Date,
KeyType: HASH
}
]
}
查询:
{
table_name: "Historic",
projection_expression: "USD,CAD",
filter_expression: "#k between :val1 and :val2",
expression_attribute_names: { "#k" => "Date" },
expression_attribute_values: {
":val1" => "2019-12-01",
":val2" => "2020-01-10"
}
}
我得到一个错误:
Aws::DynamoDB::Errors::ValidationException: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.
答案 0 :(得分:2)
您不能按-或高效进行排序-检索范围-分区键,只能按排序键进行排序。要了解原因,您需要了解DynamoDB如何存储其数据。
CreateTable operation中的“分区键”也称为“哈希键”-实际上,它的工作原理类似于哈希表中的键:DynamoDB在此键上运行哈希函数,并使用结果数字决定其大型群集的哪个节点应保留此分区。这种方法可以在整个群集中分布表,但不可能使得有效地检索按其键排序的不同分区成为可能。 “扫描”操作将以看似随机的顺序返回分区(它们很可能会通过其键的哈希函数进行排序),并且不可能有效地仅扫描一部分分区键。通过扫描整个表并仅对所需的分区进行过滤,可能会导致效率低下。如果我正确理解,这就是您要尝试做的。但这仅对小型数据库有意义-那是您的情况吗?
您已经注意到,键的另一个组成部分是“排序键”。在分区内部,在一个节点中,该分区中的不同项目按“排序键”顺序进行顺序排序。这使DynamoDB可以有效地检索按此顺序排序的它们,或仅有效地检索这些排序键的范围-Query
请求可以完成这两项操作。
因此,要实现所需的功能,您需要将日期设为排序键,而不是分区键。如何进行其余的数据建模取决于您的典型查询是什么样的:
如果您有大量股票,但是典型的查询只要求少量股票,则最合理的方法是使用股票名称作为分区键,并且正如我所说,将数据用作排序键。这样一来,您可以有效地Query
保留某一特定股票的日期范围-如果您需要3种不同的股票,则需要进行3次Query
(可以并且应该并行进行! ),但这些查询中的每一个查询都是高效的,您只需为检索到的实际数据付费,而无需进行任何后过滤。
如果存在大量不同的日期(例如,将数据保持在1秒的分辨率下),则分区可能会变得很大,出于各种原因,不建议这样做。在这种情况下,您可以通过某个粗略的时间窗口将每个分区拆分为多个分区。例如,没有为股票“ GOOG”分配一个巨大的分区,而是为“ GOOG Nov 2019”分配了一个分区,为“ GOOG Dec 2019”分配了一个分区,等等。当查询较小的日期范围时,您会知道需要哪个特定分区阅读。但是,当查询跨度超过一个月时,您将需要查询多个此类分区。请注意,非常大的查询将读取(并返回)大量数据,因此非常昂贵,因此您仅可能希望在大型分析作业中执行此操作。