【发布时间】:2014-04-24 18:02:13
【问题描述】:
假设我有一个带有id 和timestamp 属性的用户表。我希望能够查询这两个参数。如果我正确理解了文档,那么使用 DynamoDB 有两种方法:
- 使用
id作为散列,timestamp作为范围来定义一个散列+范围主键。 - 使用
id定义仅哈希主键,并使用timestamp定义全局二级索引。
每种方法的优缺点是什么?
【问题讨论】:
假设我有一个带有id 和timestamp 属性的用户表。我希望能够查询这两个参数。如果我正确理解了文档,那么使用 DynamoDB 有两种方法:
id 作为散列,timestamp 作为范围来定义一个散列+范围主键。id 定义仅哈希主键,并使用timestamp 定义全局二级索引。每种方法的优缺点是什么?
【问题讨论】:
定义一个 hash+range 主键,使用 id 作为 hash 和 timestamp 作为 范围。
通过将id 设置为Hash Key 和timestamp 为Range 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
你可以执行这些操作:
GetItem 获取基于id(哈希键)+timestamp(范围键)组合的单个项目Query 获取等于id(哈希键)的所有项目的列表如果这不是您想要的,那么 id 和 timestamp 上的哈希 + 范围分别不是您想要的。
使用 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 的缺点是:
GSI,因此请明智地选择要索引的内容GSI 将花费您额外的费用,因为您需要为其分配预置吞吐量。GSI 是最终一致的,这意味着 DynamoDB 不保证与表的哈希键关联的数据写入数据库的那一刻,数据的 GSI 哈希键立即可供查询。 DynamoDB 文档指出,这通常是即时的,但可能需要几秒钟才能使 GSI 哈希键可用。GSI 上执行GetItem 以获取基于其Hash Key / Hash Key + Range Key 的项目。您只能使用Query,它返回List
【讨论】:
This answer 可能有一些用处,但您对实现它的两种方法是正确的。
假设您使用id 作为哈希键,那么为了仅使用时间戳检索项目,您将需要一个全局二级索引。您仍然可以将timestamp 设为您的范围键,这将很有用,因为 DynamoDB 将使用它按id 对您的查询结果进行排序。
使用全局二级索引的主要缺点是您需要在表上提供额外的预置吞吐量。
【讨论】:
我也有类似的兴趣,并正在考虑在时间戳的一部分(例如,天或小时)上创建一个二级索引,作为 HASH,将 Id 作为 RANGE,以允许针对特定时间片进行查询,但这将强制时间片内的所有记录位于索引的同一分区中。
为了能够查询近期数据和历史数据,Amazon 建议采用多表设计方法 - 请参阅 https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-time-series.html。
【讨论】: