【问题标题】:DynamoDB - Single Table Many-To-Many relationships modelingDynamoDB - 单表多对多关系建模
【发布时间】:2020-04-18 12:50:35
【问题描述】:

为了更好地理解如何设计单个 DynamoDB 表,我尝试开发一个小型电影数据库应用程序。

这是我当前的 DynamoDB 表设计:

╔══════════╦════════════╦═══════════════╗
║ PK       ║ SK         ║ Title         ║
╠══════════╬════════════╬═══════════════╣
║ pk_1     ║ movie      ║ Die Hard      ║
║ pk_1     ║ actor_pk_3 ║ Bruce Willis  ║
║ pk_1     ║ tag_pk5    ║ Action        ║
║          ║            ║               ║
║ pk_2     ║ movie      ║ Looper        ║
║ pk_2     ║ actor_pk_3 ║ Bruce Willis  ║
║ pk_2     ║ actor_pk_4 ║ Emily Blunt   ║
║ pk_2     ║ tag_pk5    ║ Action        ║
║          ║            ║               ║
║ pk_3     ║ actor      ║ Bruce Willis  ║
║ pk_3     ║ movie_pk_1 ║ Die Hard      ║
║ pk_3     ║ movie_pk_2 ║ Looper        ║
║          ║            ║               ║
║ pk_4     ║ actor      ║ Emily Blunt   ║
║ pk_4     ║ movie_pk_2 ║ Looper        ║
║          ║            ║               ║
║ pk_5     ║ tag        ║ Action        ║
║ pk_5     ║ movie_pk_1 ║ Die Hard      ║
║ pk_5     ║ movie_pk_2 ║ Looper        ║
╚══════════╩════════════╩═══════════════╝

* The table has one GSI, it is just the PK and SK reversed.

我尝试设计数据库,以便始终可以通过一次查询(单次往返)获得所需的所有数据。 该设计有效,目前满足我想要的大多数访问模式。

一些例子:

  • 如果我想要电影“虎胆龙威”的所有内容,我只想查询 普通表上的“pk_1”。
  • 如果我想要所有电影,我会使用以下命令查询 GSI “电影”
  • 如果我想要电影“虎胆龙威”的所有演员,我查询“pk_1” 并且 SK 以“actor”开头
  • ...等等

这是我的大问题:

  • 这是一个好的 DynamoDB 表设计还是错误/坏的?

如果表格设计还不错,这些是我的后续问题:

  • 重复数据正常吗,我应该这样做吗?

  • 有这么多业务逻辑获取、插入和更新数据是否正常?

  • “安全”插入数据的最佳方式是什么? 先加电影,再加“actor_”和“tag_”,感觉不对,一定会失败

  • 如何确保重复数据始终与“主数据”保持一致?

  • 如何处理可能包含数百万条目的关系更新? 例如,如果我将标签“Action”重命名为“ACTION”,我将不得不用这个标签更新每部电影。 目前我只看到我批量更新它,所以数据在一定时间内并不一致。

目前我怀疑我在这张表上所做的每一个决定,因为它只是感觉来自关系数据库是错误的......

【问题讨论】:

  • 这里有一个类似的问题,针对不同的数据模型,通过一些额外的资源得到了相当彻底的答案。我不回答您的具体问题,但您可能会发现有助于理解单表策略。 stackoverflow.com/q/51055657/5563569

标签: amazon-dynamodb dynamodb-queries


【解决方案1】:

我不太了解您编写的设计,如果我误解了任何部分,请随时纠正我。主要是,我什至不明白 PK_1 是什么意思。如果我告诉你让我获得有关《虎胆龙威》的所有信息,我不明白你如何能够简单地通过你的数据库结构为我获取这些信息。我知道 pk_1 包含所有信息,但是除非您检查“pk_1”+“movie”(排序键),否则您怎么知道 pk_1 == 很难,这意味着您需要检查每部此类电影。

我会尝试先回答您的问题,然后再提出设计:

  1. 问。 [这个设计好/坏]。对于良好的 dynamoDb 设计,只要您满足所有用例并且没有错误的分区,您就可以从某个地方开始。这意味着优化频繁的写入和读取。
  2. Q [重复数据] 数据很便宜。如果重复可以使您的查询更快,则可以。理想情况下,完成请求所需的所有信息都应来自一次读取操作。
  3. Q [大量写入逻辑] 不!基于 1 和 2,您应该尝试以这样一种方式对其进行建模,以使您的写入是 ezpz。
  4. Q [您的写操作是什么样的?如果您为编写提供用例(扩展性),那么为 ddb 建模以满足您的需求会变得容易得多。然而,问题是如果你有一个新的用例。这可能需要重新设计一些数据库,因此一开始就考虑大多数用例。
  5. Q [重复数据与主数据保持相同] 使用完全一致的读取,您将始终从同步的主数据读取。您无需维护它。

我将如何设计这个 写入用例

电影信息带有元数据列表,包括流派和演员列表。

将主键保存为电影,排序键为 METADATA。现在将带有排序键的电影存储为 actor_ 作为排序键。在保存电影信息时,这将是一个额外的开销。你可以很容易地使用批量写入来做到这一点。 GSI 具有反向排序键和主键。如果您获得演员姓名作为输入,请在数据库 GSI 中搜索 action_ 以获取他们的电影。类似地,如果您想保存导演、制片人等,可以扩展此功能。针对您存储流派的属性创建另一个 GSI,并将排序键作为电影。

这样你会有两个索引,但我觉得写起来会稍微容易一些。

【讨论】:

    猜你喜欢
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 2021-04-09
    • 2021-01-13
    • 2019-08-04
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多