【问题标题】:Better method for querying DynamoDB table randomly?随机查询 DynamoDB 表的更好方法?
【发布时间】:2018-07-11 23:45:53
【问题描述】:

我已经包含了一些链接以及我们对其他答案的方法,这似乎是目前网络上最优化的。

我们的记录需要分类(例如“恐怖片”、“惊悚片”、“电视”),并且可以在特定类别和所有/某些类别中随机访问。我们通常需要一次访问大约 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 中调用它时(按使用时间计费)。

谢谢!

【问题讨论】:

    标签: amazon-web-services amazon-dynamodb


    【解决方案1】:

    跟进

    经过更多的研究和测试,我的团队决定为这些表迁移到 RDS 上托管的 MySQL。我们了解到,这是少数几个不适合 DynamoDB 的用例之一,需要重写您的用例以适应数据库(不好)。

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

    对于任何想知道我们为什么选择 MySQL 的人来说,这主要是因为 Nodejs 库可用、出色的在线资源(DynamoDB 肯定缺乏)、通过 RDS 与我们的 Lambda 轻松集成,以及迁移到 Amazon 的选项 @987654322 @数据库。

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

    如果有人有任何其他想要添加的内容或具体问题,请发表评论或给我发消息!

    【讨论】:

      【解决方案2】:

      这对于评论来说太长了,我想现在它几乎是一个完整的答案。

      方法2

      我发现我将单个项目从 dynamodb 获取到同一区域的主机的典型时间是

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

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

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

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

      方法 1

      我不确定您所说的“无需实施额外资源”是什么意思。如果您可以使用托管资源(无需实施开发工作),您还可以通过在 dynamodb 表前面放置一个 DAX 集群来使方法 1 工作。然后你可以查询到你心中的内容,而不用真正担心热分区。 (虽然缓存层意味着新/删除的项目不会立即反映。)

      【讨论】:

        猜你喜欢
        • 2016-07-21
        • 2013-03-26
        • 2012-05-16
        • 2010-12-27
        • 1970-01-01
        • 1970-01-01
        • 2011-06-07
        • 2017-10-28
        • 2012-07-20
        相关资源
        最近更新 更多