amazon-web-services - AWS DynamoDB 表设计 : Store two UserIDs and Details in Table

标签 amazon-web-services amazon-dynamodb nosql

我正在构建一个应用程序,两个用户可以在其中相互连接,并且我需要将该连接(例如友谊)存储在 DynamoDB 表中。基本上,连接表有两个字段:

  • userIdA(哈希键)
  • userIdB(排序键)

我正在考虑在 userIdB 上添加索引来查询这两个字段。我应该存储一条记录(ALICE,BOB)还是两条记录(ALICE,BOB;BOB,ALICE)的连接?第一个选项需要一次写入操作和更少的空间,但我必须查询两次才能获取用户的所有连接。第二个选项需要两次写入操作和更多空间,但我只需要查询一次 userId。

用户表包含姓名和电子邮件等详细信息:

  • userId(哈希键)
  • 名称(排序键)
  • 电子邮件

在我的应用程序中,我想在 ListView 中显示特定用户的所有连接以及用户详细信息。这意味着我有两个选择:

  1. 将已连接用户的用户详细信息也存储在连接表中,例如向该表添加两个名称字段。这很快,但如果用户名发生变化(从 Facebook 检索姓名和电子邮件),详细信息将无效,我需要更新所有条目。
  2. 使用 Batch Get 请求查询每个 userId 的用户详细信息以读取多个项目。这可能会慢一些,但我始终拥有最新的用户详细信息,并且不需要将它们存储在连接表中。

那么更好的解决方案是什么,或者还有我可能忽略的其他优点/缺点吗?

编辑

在对 NoSQL 数据库的友谊表进行一些谷歌研究后,我发现了以下两个链接:

How does Facebook maintain a list of friends for each user? Does it maintain a separate table for each user?

NoSQL Design Patterns for Relational Data

第一个链接建议使用两条记录以双向方式存储连接(或友谊),因为这样可以更轻松、更快地查询:

Connections:
    1 userIdA    userIdB
    2 userIdB    userIdA

第二个链接建议将重复数据的子集(“摘要”)保存到表中,以便仅通过一次查询即可更快地读取数据。这意味着将用户详细信息也保存到连接表中,并将 userIds 保存到用户表的属性中:

Connections:
    #    userIdA    userIdB    userDetails                    status
    1        123        456    { userId: 456, name: "Bob" }   connected
    2        456        123    { userId: 123, name: "Alice" } connected

Users:
    #     userId       name    connections
    1        123      Alice    { 456 }
    2        456        Bob    { 123 }   

此数据库模型使查询连接变得非常容易,但如果某些用户详细信息可能发生变化,则似乎很难更新。另外,我不确定是否再次需要用户表中的 userId,因为我可以轻松查询 userId。

您对该数据库模型有何看法?

最佳答案

一般来说,nosql 数据库通常与以下几个假设相结合:

  • 最终一致性是可以接受的。也就是说,如果在更新过程中某些中间答案不正确,那么在应用程序设计中通常是可以接受的。也就是说,如果在爱丽丝成为鲍勃的 friend 的几秒钟内,如果“是爱丽丝·鲍勃的 friend ”返回 true 而“是鲍勃·爱丽丝的 friend ”返回 false 就可以了

  • 性能很重要。如果您使用 nosql,通常是因为性能对您很重要。几乎可以肯定,这是因为您关心最常发生的操作的性能。 (您可能会遇到一些不常见操作的性能如此糟糕而无法执行的问题;在这种情况下,nosql 通常不是答案)

  • 您愿意降低不常见操作的速度,以提高常见操作的性能。

那么,这如何适用于您的问题。首先,它表明最终答案取决于性能。也就是说,无论人们在这里说什么,正确的答案取决于你在实践中观察到的情况。您可以尝试多种选择,看看会得到什么结果。

关于您列举的具体选项。

  • 假设性能足以让您担心 nosql 对于您的应用程序来说是一个合理的解决方案,那么几乎可以肯定您关心的是查询性能而不是更新性能。如果您使更新速度更慢且成本更高,以便查询速度更快,您可能会很高兴。这就是重点。

  • 您可能可以处理带外更新 - 这最终可能适合您。您可以将更新操作提交到 SQS 队列,而不是在页面加载期间处理它们。因此,如果有人单击确认好友按钮,您可以将请求排队以实际更新数据库。即使这涉及重建他们的用户行、重建 friend 行,甚至更新他们有多少 friend 的一些计数,也没关系。

  • 在每个方向存储一个 friend 行可能确实有意义,因此您只需要一个查询。

  • 存储用户信息(例如姓名和图片)可能确实有意义,这些信息通常显示在与好友行重复的好友列表中。请注意,每当名称或图片发生更改时,您都需要更新所有这些行。

  • 不太清楚将 friend 存储在用户表中是否有意义。那可能会变得很大。此外,保证最终一致性可能很棘手。考虑一下如果您同时处理两个用户好友关系的更新,会发生什么情况。一旦尘埃落定,不要以不一致的方式结束,这一点非常重要。

  • 每当您拥有非标准化数据(例如在每个方向上重复行或将用户信息复制到友谊表中)时,您都需要某种方法来重新验证和修复数据。您希望编写可以在后台扫描系统以查找由错误或崩溃的事件引起的不一致的代码并修复它们。

关于amazon-web-services - AWS DynamoDB 表设计 : Store two UserIDs and Details in Table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44358902/

相关文章:

amazon-web-services - AWS CloudFormation - 将新证书添加到现有监听器

python - 在 AWS Lambda 中连接 AWS RDS (psql)

mysql - 我的大型 MySQL 表应使用哪种 AWS 服务?

python - 为什么这些查询之间的 dynamodb 性能不同?

azure - DocumentDB 存储过程每个请求只返回 100 个文档?

database - 将 MongoDB 数据库连接到 MATLAB 时出错(无法加载消息目录 'mongodb:mongodb')

amazon-web-services - 如何将 VPC 和安全组分配给 AWS CDK 中的 Lambda?

mysql - 在 AWS 中使用 MySQL 触发器清空更新和插入缓存

c# - 尝试在 DynamoDb 中保存枚举时出现“类型不受支持”错误

Redis 分片性能和获取 key 的 o(1) 时间复杂度