当日期是唯一键时,查询日期范围

时间:2020-01-22 20:27:29

标签: amazon-dynamodb dynamodb-queries

我想使用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.

1 个答案:

答案 0 :(得分:2)

您不能按-或高效进行排序-检索范围-分区键,只能按排序键进行排序。要了解原因,您需要了解DynamoDB如何存储其数据。

CreateTable operation中的“分区键”也称为“哈希键”-实际上,它的工作原理类似于哈希表中的键:DynamoDB在此键上运行哈希函数,并使用结果数字决定其大型群集的哪个节点应保留此分区。这种方法可以在整个群集中分布表,但不可能使得有效地检索按其键排序的不同分区成为可能。 “扫描”操作将以看似随机的顺序返回分区(它们很可能会通过其键的哈希函数进行排序),并且不可能有效地仅扫描一部分分区键。通过扫描整个表并仅对所需的分区进行过滤,可能会导致效率低下。如果我正确理解,这就是您要尝试做的。但这仅对小型数据库有意义-那是您的情况吗?

您已经注意到,键的另一个组成部分是“排序键”。在分区内部,在一个节点中,该分区中的不同项目按“排序键”顺序进行顺序排序。这使DynamoDB可以有效地检索按此顺序排序的它们,或仅有效地检索这些排序键的范围-Query请求可以完成这两项操作。

因此,要实现所需的功能,您需要将日期设为排序键,而不是分区键。如何进行其余的数据建模取决于您的典型查询是什么样的:

如果您有大量股票,但是典型的查询只要求少量股票,则最合理的方法是使用股票名称作为分区键,并且正如我所说,将数据用作排序键。这样一来,您可以有效地Query保留某一特定股票的日期范围-如果您需要3种不同的股票,则需要进行3次Query(可以并且应该并行进行! ),但这些查询中的每一个查询都是高效的,您只需为检索到的实际数据付费,而无需进行任何后过滤。

如果存在大量不同的日期(例如,将数据保持在1秒的分辨率下),则分区可能会变得很大,出于各种原因,不建议这样做。在这种情况下,您可以通过某个粗略的时间窗口将每个分区拆分为多个分区。例如,没有为股票“ GOOG”分配一个巨大的分区,而是为“ GOOG Nov 2019”分配了一个分区,为“ GOOG Dec 2019”分配了一个分区,等等。当查询较小的日期范围时,您会知道需要哪个特定分区阅读。但是,当查询跨度超过一个月时,您将需要查询多个此类分区。请注意,非常大的查询将读取(并返回)大量数据,因此非常昂贵,因此您仅可能希望在大型分析作业中执行此操作。