DynamoDb 表设计:单表或多表
Posted
技术标签:
【中文标题】DynamoDb 表设计:单表或多表【英文标题】:DynamoDb table design: Single table or multiple tables 【发布时间】:2017-05-13 00:37:58 【问题描述】:我对 NoSQL 和 DynamoDB 还很陌生,而且我习惯使用 RDBMS。我正在为游戏设计数据库,我们使用 DynamoDB 和 AWS Lambda 作为后端。我为包含用户信息和资源的玩家资料创建了一个表名“Users”。因为游戏有库存系统,所以我还创建了一个表名“UserItems”。
这一切都很好,直到我意识到 DynamoDB 没有事务并且在两个表上执行的任何操作(例如使用增加资源的项目)都有可能在一个表上失败而在另一个表上成功并且会导致丢失影响我们客户的数据。
所以我在想我的多表设计可能不好,因为我在使用 RDBMS 时设计多表是我的习惯。这让我想到将整个“UserItems”存储为“Users”中的哈希,但我不确定这是一个好习惯,因为 Users 表中单行的大小会非常大(我们可能有 500 个唯一项目每个用户),每次我从/向“用户”(大多数时候不需要“UserItems”数据)拉取或放入数据时,读/写吞吐量也会非常大。
我应该怎么做,保持多表设计并手动处理事务或切换到单表设计?或者也许有第三种选择?
更新:关于我的用例的更多信息
目前我有 2 张桌子
用户:UserId(密钥)、用户名、Gold UserItems:UserId(分区键)、ItemId(排序键)、名称、GoldValue场景:
-
用户购买物品:将推导出Users.Gold,将新的UserItem添加到UserItems表中。
用户出售物品:Users.Gold 将增加,该物品将从 UserItems 表中删除。
在上述两种情况下,我都必须对 2 个没有事务的表执行 2 次更新操作,其中一个可能会失败。
为了解决这个问题,我考虑使用单表解决方案,这是一个包含 4 列 UserId(key)、Username、Gold、UserItems 的单用户表。但是有两件事我很担心:
-
UserItems 中的数据对于单个单元格而言可能会变得很大,因为一个用户最多可以拥有 500 个项目。
要添加/删除项目,我必须从 dynamodb 中提取用户项目,添加/删除项目,然后将其放回用户。所以我必须为 1 次操作执行 1 次读取和 1 次写入操作。由于问题 (1),读/写数据的大小可能会变得非常大。
【问题讨论】:
【参考方案1】:FWIW,NoSQL Design for DynamoDB 上的 AWS 文档建议使用单个表:
作为一般规则,您应该在一个 DynamoDB 应用程序。如前所述,大多数精心设计的 应用程序只需要一个表,除非有特定原因 用于使用多个表。
涉及大量时间序列数据的情况除外, 或具有非常不同的访问模式的数据集——但这些是 例外。具有倒排索引的单表通常可以启用 用于创建和检索复杂分层数据的简单查询 您的应用程序所需的结构。
【讨论】:
对我来说很奇怪...他们说大多数应用程序只需要一个表,但他们的两个用例之一使用三个表docs.aws.amazon.com/amazondynamodb/latest/developerguide/… 好点@MichaelBrown。只需关注this tutorial,他们似乎每个实体都使用一张表,没有任何区别。让人难以抉择。然而,这都是每个人的好见解。 @MichaelBrown 我认为这只是为了简单起见 - 这是一个为绝对初学者准备的教程,所以明智的做法是不要让读者一开始就陷入高级概念 我实际上上过关于 noSQL 设计的高级课程,整个“单表”规则甚至都不是一个好规则。【参考方案2】:NoSql 数据库最适合非事务性数据。如果您将规范化(将数据拆分到多个表中)引入 noSQL,那么您就违背了它的全部目的。如果性能是最重要的,那么您应该考虑只为您的用例提供一个表。 DynamoDB 支持范围键,也支持二级索引。对于您的用例,最好重新设计您的表格以使用范围键。 如果您可以分享有关当前表格的更多详细信息,也许我可以帮助您提供更多信息。
【讨论】:
感谢您的回答。似乎单表是我用例的解决方案。当我将所有内容存储在一个表中时,我仍然担心单行中的数据大小和读/写过程。我已经更新了我的问题。我希望它可以帮助您了解我的情况。 aws.amazon.com/blogs/developer/… 不幸的是,我使用的是 Lambda 的 NodeJs,还没有 JS 的事务库。以上是关于DynamoDb 表设计:单表或多表的主要内容,如果未能解决你的问题,请参考以下文章
在 AWS Amplify GraphQL DynamoDB 中按另一个表的字段(也称为交叉表或嵌套过滤)过滤列表查询