使用DynamoDB进行N对N建模

4
我正在参与一个项目,其中使用DynamoDB作为大部分持久数据的存储。我现在正试图对数据结构进行建模,使其更像传统SQL数据库中的建模方式,但我也希望探讨好的NoSQL设计方案,以适应这种类型的数据。
例如,考虑一种简单的N到N关系,比如将物品分组到类别中。在SQL中,可能会使用连接表来建模,例如:
items
-----
item_id (PK)
name

categories
----------
category_id (PK)
name

item_categories
---------------
item_id     (PK)
category_id (PK)

要列出一个类别中的所有项目,可以执行如下连接操作:
SELECT items.name from items 
  JOIN item_categories ON items.item_id = item_categories.item_id
  WHERE item_categories.category_id = ?

要列出一个项目所属的所有类别,可以进行相应的查询:

SELECT categories.name from categories 
  JOIN item_categories ON categories.category_id = item_categories.category_id 
  WHERE item_categories.item_id = ?

在一般情况下,以及在像DynamoDB这样的NoSQL数据库中,是否有希望以相当高效的方式(不需要很多(N,甚至?)单独操作)对这样的关系进行建模,特别是针对像上面那样的简单用例 - 当没有等价于JOIN时?
还是应该选择RDS?
我考虑过以下几点:
1. 将类别作为项目内的数组。这使得查找项目的类别变得容易,但无法解决获取类别内所有项目的问题。而且我需要在每个项目中复制所需的属性,例如类别名称等。更新类别会很麻烦。
2. 为每个类别重复每个项目,并使用category_id作为范围键,并添加一个反向的GSI(category_id作为哈希,item_id作为范围)。虽然去规范化对于NoSQL来说很常见,但我仍然有些疑虑。可能将项目分成itemsitem_details,只复制列表等中需要的最常见的属性。
3. 使用连接表将项目与类别相互映射。使用[item_id, category_id]作为键,[category_id, item_id]作为GSI,以支持两个查询。在这里复制最常见的属性(名称等)。要获取类别的所有完整项目,仍需要执行一个query,然后进行N个get操作,这会消耗大量CU。更新项目或类别名称将需要多个update操作,但并不太困难。
我的困境是数据本身的格式非常适合文档数据库,而我需要的关系适合SQL数据库。如果可能的话,我想继续使用DynamoDB,但显然不是任何代价...
1个回答

3

你已经朝着正确的方向看了!

为了做出明智的决策,你还需要考虑数据的基数:

你期望只有很少的分类(少于十个吗?)或者很多分类(例如数百个、数千个、数万个等等)?

每个类别中的项目如何:你期望有很多类别,其中每个类别只有几个项目,还是有一些类别,但是其中有很多项目?

接下来,你需要考虑整个数据集以及各种类型查询的基数。你是否通常只需要检索单个分类中的项目?或者你主要进行单独检索项目的查询,并且只需要统计每个类别中的项目数量等。

最后,请考虑预期的数据集随时间的增长情况。只要你的查询分区良好,DynamoDB通常会在规模上优于RDBMS。

特别是在规模上,考虑每种查询类型的可接受延迟。例如,如果你期望有数百个类别,每个类别都有数千个以上的项目,那么检索类别中的所有项目意味着什么?当然你不会同时将它们全部显示给用户。

我建议你还应该考虑使用另一种数据存储与DynamoDB配套,例如ElasticSearch或Redis集群,如果需要对数据进行统计。

最后,如果聚合查询或连接对于你的用例至关重要,或者如果大规模的数据集通常可以在单个RDBMS实例上轻松处理,那么不要试图让方形钉子适应圆形洞。类似Aurora的托管RDBMS解决方案可能更合适。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接