DynamoDB-单表多对多关系建模

时间:2019-12-29 12:52:46

标签: amazon-dynamodb dynamodb-queries

为了更好地理解如何设计一个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.

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

一些例子:

  • 如果我想要电影《 Die Hard》的所有内容,我只会查询 普通表上的“ pk_1”。
  • 如果我想要所有电影,请使用以下命令查询GSI “电影”
  • 如果我希望电影《 Die Hard》的所有演员都可以查询“ pk_1” 而SK以“演员”开头
  • ...等等

这是我的大问题:

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

如果桌子的设计还不错,那么这些是我的后续问题:

  • 重复的数据是否正常,应该这样吗?

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

  • “安全地”插入数据的最佳方法是什么? 首先添加电影,然后添加“ actor_”和“ tag_”感觉不对,并且注定会在某个时间失败

  • 如何确保重复的数据始终与“主”保持相同?

  • 如何处理可能具有数百万个条目的关系的更新? 例如,如果我将标签“ Action”重命名为“ ACTION”,则必须使用此标签更新每部电影。 目前,我只能批量查看更新,因此在一定时间内数据不一致。

当前,我对我在此表上所做的每个决定都表示怀疑,因为从关系数据库中感觉到这是错误的...

1 个答案:

答案 0 :(得分:0)

我不太了解您编写的设计,因此如果我误解了任何部分,请随时纠正我。主要是,我什至不了解PK_1的意思。如果我告诉您让我获得有关Die Hard的所有信息,那么我将不明白您将如何仅通过数据库结构就能为我获取这些信息。我得到pk_1的所有信息,但是如何知道pk_1 ==死了,除非您选中“ pk_1” +“电影”(排序键),否则这意味着您需要检查每部这样的电影。

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

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

我将如何设计 写用例

电影信息附带元数据列表,包括类型和演员列表。

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

您将以这种方式有两个索引,但是我觉得写会稍微容易一些。