使一对多关系适应 DynamoDB (NoSQL)

Adapting one-to-many relationship to DynamoDB (NoSQL)

简介

您好,由于稳定​​性、性能等原因,我正在转向 AWS。我将使用 DynamoDB,因为始终免费的套餐可以让我大大减少账单。直到现在我一直在使用 MySQL。对于这个示例,我将简化属性(以显示我需要帮助的实际位置并缩短问题)。

我的实际数据库只有不到 5k 行,我预计它会在 2 年内增长到 20-30k。每个用户(没有任何 group/order 数据)大约 600B。我不知道这将如何转化为 NoSQL 数据库,但我希望它小于 10MB。

我会有什么数据?

用户:

群组:

订单:

关系:

我将如何访问数据以及我将获得什么?

  1. 我将通过用户名访问用户(我不知道他所在的组)。我将需要获取用户的数据,他所属的组及其数据。
  2. 我将访问属于某个组的用户。我需要获取用户数据和群组数据。
  3. 我将通过 oid 访问订单。我需要获取它所属的用户及其数据。

我试过的

我观看了 Gary Jennings 的一系列视频,阅读了关于 SO 的答案,还阅读了 alexdebrie 关于一对多关系的文章。我的问题是我似乎找不到适合我访问数据的所有方式的替代方案。

例如:

  1. 非规范化:它会给我留下很多重复的数据,从而增加成本。
  2. 复合主键:我将能够按组访问用户,但如何在事先不知道组的情况下访问用户和组的数据。我将需要使用 2 个请求,使其效率低下并增加成本。
  3. 二级索引 + 查询 API 操作:同样,我将需要使用 2 个请求,这使其效率低下并增加了成本。

最后的问题

通过提前阐明您的访问模式,您有了一个良好的开端。

让我们首先谈谈您对 DynamoDB 中数据建模的一些评论:

  1. Denormalization: it will leave me with a lot of duplicated data thus increasing the cost.

当第一次学习 DynamoDB 数据建模时,先前的 SQL 数据库知识可能 确实 妨碍学习。使用 SQL 数据库时,规范化数据是一种常见做法。但是,对数据进行非规范化是 DynamoDB 中的一个关键数据建模策略。

一个 BIG 您想要对数据进行非规范化的原因:DynamoDB 没有连接。因为 DDB 没有联接,所以您可以很好地 pre-join 您的数据,因此可以在单个查询中获取它。

这个 blog post 很好地解释了为什么非规范化在 DDB 中很重要。

记住,存储很便宜。非正规化数据可以以相对较低的成本实现更快的数据访问。根据您的数据库的大小,您可能 很好 在免费套餐门槛之下。不要强调重复数据!

  1. Composite primary key: I will be able to access the users by its group but how will I access the user and the group's data without knowing the group beforehand. I would need to use 2 requests making it inefficient and increasing the costs.

非规范化数据将有助于解决此问题(例如,存储用户的组信息)。我将在下面给你举个例子。

  1. Secondary index + the Query API action: Again I would need to use 2 requests making it inefficient and increasing the costs.

你没有分享你的主键结构,所以我不确定什么场景需要两次请求。但是,我要说的是,在某些情况下,向 DDB 发出两个请求可能是一种合理的方法。进行两次高效的查询操作并不是世界末日。

好的,我们来看一个关系建模的例子!请记住,有多种方法可以在 DynamoDB 中对数据进行建模。此示例不是 THE 方式。相反,这是一个示例,旨在展示一些可能有用的策略。

这是您的数据模型之一:

通过这种安排,您可以支持以下访问模式:

  1. 获取用户信息 - PK = USER#[用户名] SK = USER#[用户名]
  2. 获取用户组 - PK = USER#[用户名] SK begins_with GROUP#。请注意,我对组项中的用户数据进行了非规范化处理。这样做的原因很快就会显而易见:)
  3. 获取用户订单 - PK = USER#[username] SK begins_with ORDER#
  4. 获取所有用户数据 - PK = USER#[username]

为了支持您的其余访问模式,我创建了一个二级索引。二级索引的主键和排序键与基 table 的主键 key/sort 交换。这种模式称为 inverted index。二级索引如下所示:

该二级索引支持以下访问模式:

  • 获取组用户 - PK = GROUP#[grouped]
  • 通过 oid 获取订单 - PK = ORDER#[oid]

您可以看到,我通过在代表组的项目中重复用户数据来使用户和组关系非规范化。这有助于我使用“获取组用户”访问模式。

同样,这只是实现您描述的访问模式的一种方式。有很多策略,但很多都要求您放弃使用 SQL 数据库时学到的一些最佳实践!