我一直在思考查询未绑定项目数量的可能策略。
例如,考虑一个论坛-您可以按主题对任意数量的论坛帖子进行分类。您需要至少支持两种访问方式:帖子详细信息视图和按主题列出的帖子。
// legend
PK = partition key, SK = sort key
虽然很容易获得一条帖子,但是如果不进行扫描,就无法有效地查询帖子列表。
PK = postId
非常适合查询给定主题的所有帖子,但所有帖子都位于同一分区(“热分区”)中。
PK = topic and SK = postId#addedDateTime
将项目存储在存储桶中,例如每天存储一个新存储桶。这会将大量逻辑推到应用程序层并增加延迟。例如,如果您需要获得10个帖子,则必须查询今天的存储桶,如果存储桶中的物品少于10个,查询昨天的存储桶,等等。如果跨过水桶,那可能是一场噩梦。
PK = topic#date and SK = postId#addedDateTime
所以我的问题是,如何以“ DynamoDB方式”存储和查询未绑定的项目列表?
答案 0 :(得分:1)
我认为您对选择有很好的了解。
我不知道要了解一种真正的方式来解决DynamoDB中的这一特定问题,但是为了讨论,我将抛出一些想法。
虽然很容易获得一条帖子,但是如果不进行扫描,就无法有效地查询帖子列表。
如果您的主键仅由postId
组成,那肯定是这种情况(我将使用POST#<postId>
使其更易于阅读)。该表将如下所示:
对于“获取帖子详细信息视图(又名按ID获取帖子)”访问模式,这将是 super 高效的方法。但是,我们没有内置任何方式来访问一组帖子按主题。下一个镜头。
有几种方法可以对帖子和主题之间的一对多关系进行建模。首先想到的是在topic
字段上创建二级索引。从逻辑上来说,看起来像这样:
现在,我们可以使用有效的query
操作按主题获取帖子的项目集合。如果每个主题的帖子数量增加,分页将为您提供帮助。这对于您的应用程序可能就足够了。为了便于讨论,我们假设它创建了一个热分区,并考虑了可以采用哪些策略来减少该问题。
一个选项
你说
将项目存储在存储桶中,例如每天存储一个新存储桶。
这是一个好主意!让我们将辅助索引分区键更新为<topic>#<truncated_timestamp>
,以便我们可以在给定的时间范围(天/周/月/月/等)内按主题对帖子进行分组。
我在这里做了几件事:
POST#1
和POST#2
都在9月具有posted_at
时间戳。我将这两个时间戳都截断为2020-09-01
,以表示9月份的整个月份(或对您的应用有意义的任何时间范围)。这将有助于跨分区分配数据,从而减少热键问题。如您正确指出的那样,这将增加应用程序逻辑的复杂性,并增加延迟,因为您可能需要发出多个请求来检索足够的结果以满足应用程序的需求。但是,在这种情况下,可能是一个合理的权衡。如果增加延迟是一个问题,则可以预先填充一个分区,以包含前N个月值得进行主题讨论的结果(例如,PK = TOPIC_CACHE#<topic>
的list属性包含前N个postId的列表)个月)。
如果TOPIC_CACHE
最终成为热分区,则可以始终使用计算出的后缀对分区进行分片:
您的应用程序在检索主题缓存时可以在1..N之间随机选择一个TOPIC_CACHE。
有许多方法可以处理这种访问模式,这些选项仅代表了少数可能性。如果是我的应用程序,那么我将从使用Post主题作为分区键创建二级索引开始。这是最容易实现的方法,它将使我有机会了解我的应用程序访问模式在生产环境中的表现。如果热键问题开始成为问题,我将更深入地研究某种缓存解决方案。