【问题标题】:DynamoDB: range vs. global secondary indexDynamoDB:范围与全局二级索引
【发布时间】:2014-04-24 18:02:13
【问题描述】:

假设我有一个带有idtimestamp 属性的用户表。我希望能够查询这两个参数。如果我正确理解了文档,那么使用 DynamoDB 有两种方法:

  1. 使用id 作为散列,timestamp 作为范围来定义一个散列+范围主键。
  2. 使用id 定义仅哈希主键,并使用timestamp 定义全局二级索引。

每种方法的优缺点是什么?

【问题讨论】:

    标签: database amazon-dynamodb


    【解决方案1】:

    定义一个 hash+range 主键,使用 id 作为 hash 和 timestamp 作为 范围。

    通过将id 设置为Hash KeytimestampRange Key,您实际上是在创建一个“复合主键”。

    换句话说,您的 DynamoDB 架构将允许以下数据(注意“john”重复了 3 次)

    id (Hash) | timestamp (Range)
    ----------|-------------------------
    john      | 2014-04-28T07:53:29.000Z
    john      | 2014-04-28T08:53:29.000Z
    john      | 2014-04-28T09:53:29.000Z
    mary      | 2014-04-28T07:53:29.000Z
    jane      | 2014-04-28T07:53:29.000Z
    

    你可以执行这些操作:

    1. GetItem 获取基于id(哈希键)+timestamp(范围键)组合的单个项目
    2. Query 获取等于id(哈希键)的所有项目的列表

    如果这不是您想要的,那么 idtimestamp 上的哈希 + 范围分别不是您想要的。

    使用 id 定义一个仅哈希的主键并定义一个全局辅助键 使用时间戳索引。

    id 上使用仅哈希主键,id 必须是唯一的。

    id (Hash) | timestamp (GSI Hash Key)
    ----------|-------------------------
    john      | 2014-04-28T07:53:29.000Z
    mary      | 2014-04-28T07:53:29.000Z
    jane      | 2014-04-28T07:53:29.000Z
    

    然后通过在timestamp 上应用GSI hash-only,您将能够查询ids 的列表以获取特定timestamp

    这种方法的好处在于,它绝对是您的用例的正确解决方案。 #1 滥用范围键(除非您打算在应用程序级别确保 id 不重复,这可能是个坏主意)。

    使用GSI缺点是:

    1. 每个表最多只能有 5 个GSI,因此请明智地选择要索引的内容 DynamoDB 2019 年 12 月更新 - 您现在可以创建多达 20 个 @987654344 @ per table,并且可以通过请求进一步提高这个软限制https://aws.amazon.com/about-aws/whats-new/2018/12/amazon-dynamodb-increases-the-number-of-global-secondary-indexes-and-projected-index-attributes-you-can-create-per-table/
    2. GSI 将花费您额外的费用,因为您需要为其分配预置吞吐量。
    3. GSI 是最终一致的,这意味着 DynamoDB 不保证与表的哈希键关联的数据写入数据库的那一刻,数据的 GSI 哈希键立即可供查询。 DynamoDB 文档指出,这通常是即时的,但可能需要几秒钟才能使 GSI 哈希键可用。
    4. 您不能在GSI 上执行GetItem 以获取基于其Hash Key / Hash Key + Range Key 的项目。您只能使用Query,它返回List

    【讨论】:

    • 感谢您的出色回答。我将 RFC 4122 UUID 用于 ID 属性,因此您对解决方案 #1 滥用范围键的评论可能是公平的。然而,这个缺点只是概念上的,而使用 GSI 的缺点是非常明显的。不过,这绝对让我有所思考。
    • 我相信您现在可以随时更改 GSI。
    • 如果表使用简单的主键,还能查询吗?我认为您只能使用简单的主键(没有范围的哈希)扫描表。
    【解决方案2】:

    This answer 可能有一些用处,但您对实现它的两种方法是正确的。

    假设您使用id 作为哈希键,那么为了仅使用时间戳检索项目,您将需要一个全局二级索引。您仍然可以将timestamp 设为您的范围键,这将很有用,因为 DynamoDB 将使用它按id 对您的查询结果进行排序。

    使用全局二级索引的主要缺点是您需要在表上提供额外的预置吞吐量。

    【讨论】:

    • 你的意思是即使我有hash+range键组合,如果我只想查询范围键,我还需要定义范围键作为全局二级索引?
    • @batmaci - 是的,只要您想在 DynamoDB 中执行查询,您就需要指定哈希键,无论是表的主哈希键还是索引的哈希键。将 DynamoDB 视为一个哈希表 - 如果您没有它们的键,那么您必须扫描整个表。
    【解决方案3】:

    我也有类似的兴趣,并正在考虑在时间戳的一部分(例如,天或小时)上创建一个二级索引,作为 HASH,将 Id 作为 RANGE,以允许针对特定时间片进行查询,但这将强制时间片内的所有记录位于索引的同一分区中。

    为了能够查询近期数据和历史数据,Amazon 建议采用多表设计方法 - 请参阅 https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-time-series.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      • 1970-01-01
      • 2018-11-01
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 2022-11-21
      相关资源
      最近更新 更多