随机查询DynamoDB表的更好方法?

时间:2018-07-11 23:45:53

标签: amazon-web-services amazon-dynamodb

我已经提供了一些链接以及我们对其他答案的使用方法,这似乎是目前网络上最合适的。

我们的记录需要分类(例如,“恐怖”,“惊悚”,“电视”),并且可以在特定类别和所有/某些类别中随机访问。我们通常一次需要访问大约20-100个项目。我们的类别数量也很少(少于100个)。

我们写数据库来上传/删除内容,尽管这是分批完成的,不需要实时。

我们尝试了两种具有两种不同数据结构的方法。

方法1

AWS DynamoDB - Pick a record/item randomly?

Help selecting nth record in query.

简而言之,将类别用作哈希键,并将UUID用作排序键。生成一个随机UUID,使用大于或小于此值查询Dynamo,并将其限制为1。AWS员工甚至在第二个链接中建议这样做。 (我们还尝试增加对所需项目数的限制,但这增加了查询第一次失败的可能性。)

问题在于这种方法:

  • 如果第一个查询大于或小于任何UUID,则查询可能会失败
  • 在任何特定类别上进行查询都会导致大规模节流(少量分区)

我们还考虑为每个类别添加一个后缀,以人为地增加我们拥有的分区的数量,如以下链接所示。

AWS Database Blog Choosing the Right DynamoDB Partition Key

方法2

Amazon Web Services: How do we get random item from the dynamoDb's table?

做类似的事情,我们将类别与序列号连接起来,并将其用作哈希键。例如恐怖-000001。

通过了解每个类别中的记录数,我们可以对整个数据集执行随机查询,同时还避免了热分区/键。

以这种方式发行

  • 我们需要一个辅助数据结构来管理每个类别的顺序计数
  • 编写(尤其是删除)的过程要复杂得多,尽管并不需要实时进行。

结论

这两种方法都可以解决我们对类别进行随机查询的主要用例,但是它们提供的缺点实际上阻止了我们使用它们。我们更加倾向于使用后缀来解决热分区问题的方法#1,尽管对于失败的查询,我们需要额外的重试逻辑。

是否有更好的方法来解决此问题?专门寻找能够很好扩展(无需扫描)且无需实施额外资源的解决方案。 #1符合要求,但是需要管理后缀和失败的尝试确实阻止了我们使用它,特别是当它在lambda中被调用时(根据使用时间计费)。

谢谢!

2 个答案:

答案 0 :(得分:0)

跟进

经过更多的研究和测试,我的团队决定转向这些表的RDS上托管的MySQL。我们了解到,这是DynamoDB不适合使用的少数用例之一,因此需要重写您的用例以适合数据库(不良)。

我们认为在DynamoDB上集成随机采样所需的额外复杂性是不值得的,并且我们无法提出任何可比的解决方案。但是,由于价格和响应时间的原因,我们不需要持久访问DynamoDB的表。

对于任何想知道我们为什么选择MySQL的人来说,这在很大程度上是由于可用的Nodejs库,强大的在线资源(DynamoDB绝对缺少),可通过RDS与我们的Lambda轻松集成以及迁移到亚马逊的选项Aurora数据库。

我们也研究了PostgreSQL,但对client库或admin工具并不满意,我们相信MySQL可以满足我们对这些表的需求。

如果还有其他要添加的内容或特定问题,请发表评论或给我发送消息!

答案 1 :(得分:0)

这个评论太长了,我想现在这是一个完整的答案。

方法2

我发现从dynamodb到同一区域中的主机获取单个项目的典型时间是<10ms。只要您可以接受最多1-2个额外的呼叫,就可以轻松实现方法2。

如果您仅使用GSI键,而GSI类别是您的哈希键,表的主键是您的范围键,则可以快速找到类别中编号最大的单个项目。

添加新项目时,请从GSI中找到该类别的最大编号,然后将新项目写入序列号为n + 1的表中。

删除时,从GSI中找到该类别具有最大序列号的项目,覆盖要删除的项目,然后从序列号最高的位置删除现在重复的项目。

要随机获取一个项目,请查询GSI以找到类别中编号最高的项目,然后随机选择一个数字,因为您现在知道有效范围。

方法1

当您说“不需要实施额外的资源”时,我不确定您的意思。如果您可以使用托管资源(无需实现任何开发工作),也可以通过将DAX群集放在dynamodb表的前面来使方法1起作用。然后,您可以查询自己内心的内容,而无需真正担心热分区。 (尽管缓存层意味着新的/删除的项目不会立即反映出来。)