3

记住在 DynamoDB 中使用尽可能唯一的分区键在分区之间均匀分布项目的最佳实践,我遇到了一个问题。

假设我的表存储诸如usersitems之类的项目devices。我将这些项目中的每一个的 id 存储为分区键。每个 id 都以其类型为前缀,例如user-XXXX, item-XXXX& device-XXXX

现在的问题是如何只查询某种类型的对象?例如我想检索 all users,我该怎么做?如果begin_with允许运算符用于分区键,那么我可以搜索前缀,但分区键只允许相等运算符,这是可能的。

如果现在我使用我的类型作为分区键,例如,user作为分区键,然后user-id作为排序键,它会起作用,但它只会导致几个分区键,从而导致热键问题。创建多个表是一种不好的做法。

欢迎任何建议。

4

2 回答 2

2

这是一个很好的问题。我也很想听听其他人正在做什么来解决这个问题。

如果您使用 的分区键存储数据<type>-<id>,则您支持“按 ID 检索项目”的访问模式。您已经正确地注意到您不能begins_with在分区键上使用,这让您没有明确的方法来获取该类型项目的集合。

我认为您使用有意义的排序键创建<type>(例如UsersDevices等)的分区键是正确的。但是,由于您的项目没有均匀地分布在整个表中,您将面临热分区的可能性。

解决热分区问题的一种方法是使用外部缓存,这将防止您的数据库每次都被命中。这会带来额外的复杂性,您可能不想将其引入应用程序,但这是一种选择。

您还可以选择在 DynamoDB 中跨分区分布数据,从而有效地实现您自己的缓存。例如,假设您有一个 Web 应用程序,该应用程序的主页上直接列出了“前 10 台设备”。您可以创建分区DEVICES#1, DEVICES#2, DEVICES#3,...,DEVICES#N每个分区都存储前 10 个设备。当您的应用程序需要获取前 10 个设备时,它可以随机选择这些分区之一来获取数据。这可能不适用于像 一样大的分区Users,但要考虑一个非常简洁的模式。

进一步扩展这个想法,您可以通过一些其他有意义的指标(例如<manufactured_date><created_at>)对设备进行分区。这将使您的项目更均匀地分布在Device整个数据库中。您的应用程序将负责查询所有分区并合并结果,但您将减少/消除热分区问题。AWS DynamoDB 文档更深入地讨论了这种模式。

DynamoDB 数据建模几乎没有一种万能的方法,这会使数据建模变得非常棘手!您的特定访问模式将决定哪种解决方案最适合您的方案。

于 2020-09-10T18:22:49.533 回答
1

牢记拥有单个表并跨分区均匀分布项目的最佳实践

快速强调这里提到的两件事。

  1. 绝对均匀分布分区键是最佳实践。
  2. 在一般意义上,将记录放在单个表中是为了避免像在关系数据库中那样进行规范化。换句话说,使用重复/冗余信息构建它很好。因此,将所有可能的数据组合到一个表中不一定是一个概念。

现在的问题是如何只查询某种类型的对象?例如我想检索所有用户,我该怎么做?

假设您有这个表,其中只有“用户”数据。这是否允许检索所有用户?当然不是,除非有一个类型为 user 的分区,其余部分在 userid 的排序键后面。

创建多个表是一种不好的做法

我认为拥有不止一张桌子被认为是不好的。如果我们像规范化表一样存储并且必须使用 JOIN 将数据放在一起,那就不好了。

话虽如此,有什么更好的方法可以遵循。

  1. 根本区别在于首先考虑查询以在表设计中派生。这甚至会表明 DynamoDB 是否是正确的选择。例如,选择每个用户的要求对于 DynamoDB 来说可能完全是一个不好的用例来解决。
  2. 查询模式将进一步建议手头最好的分区键是什么。在这里选择 DynamoDB 是因为高摄取量和大部分不可变的写入吗?
  3. 我是否总是手头有分区键来执行我需要执行的选择?
  4. 更新语句会是什么样子,它会再次具有分区键来执行更新吗?
  5. 我是否需要按其他列进一步过滤,这可以是默认排序顺序吗?

当您开始回答其中一些问题时,可能会出现更好的模型。

于 2020-09-11T03:00:56.527 回答