我认为您有很多选择,但这里有一个可能基于您的应用程序具有时间感知能力的假设,即您想要查询最后 N 分钟、几小时、几天等内的交互。
hash_key = userA
range_key = [iso1860_timestamp][1]+userB+uuid
首先,uuid 技巧是为了避免覆盖用户A 和用户B 之间同时发生的交互记录(可能发生取决于时钟的粒度/精度)。所以在插入方面我们是安全的:没有重复,没有覆盖。
查询方面,事情是这样完成的:
- 检索所有访问 UserA 个人资料的 UserB,以唯一(= 没有双重 UserB)并按时间排序。
query(hash_key=userA, range_key_condition=BEGIN(common_prefix))
其中common_prefix
= 2013-01-01 表示 2013 年 1 月的所有交互
这将检索一个时间范围内的所有记录,排序(假设它们以正确的顺序插入)。然后在应用程序代码中过滤它们以仅保留与 userB 有关的那些。不幸的是,DynamoDB API 不支持范围键条件列表(否则您可以通过传递额外的 CONTAINS userB 条件来节省一些时间)。
query(hash_key=userA, range_key_condition=BEGINS(common_prefix))
如果我们可以假设您知道交互的时间戳,哪里common_prefix
会更精确。
当然,应该根据您将处理的数据流的属性来评估这种设计。如果您可以(大多数情况下)为您的查询指定一个有意义的时间范围,它将很快并且受您在用户A 的时间范围内记录的交互次数的限制。
如果您的应用程序不是那么面向时间 - 我们可以假设用户通常只有少数交互 - 您可能会切换到以下模式:
hash_key = userA
range_key = userB+[iso1860_timestamp][1]+uuid
这样您就可以按用户查询:
query(hash_key=userA, range_key_condition=BEGIN(userB))
这种替代方法将很快,并且受所有时间范围内userA-userB 交互的 nber 限制,这取决于您的应用程序,这可能是有意义的。
所以基本上你应该检查示例数据并估计哪个方向对你的应用程序有意义。两个方向(时间或用户)也可以通过在其他表中手动创建和维护索引来加速 - 以更复杂的应用程序代码为代价。
(历史版本:避免使用基于时间的键覆盖记录的技巧)在您的情况下,一个常见的技巧是使用生成的唯一 id ( uuid
) 对范围键进行后缀。这样您仍然可以query
使用条件调用BETWEEN
来检索在给定时间段内插入的记录,并且您无需担心插入时的键冲突。