AWS DynamoDB表设计:在表中存储两个UserID和详细信息

时间:2017-06-04 21:20:37

标签: amazon-web-services amazon-dynamodb nosql

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

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

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

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

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

在我的应用中,我想在列表视图中显示某个用户的所有连接以及用户详细信息。这意味着我有两个选择:

  1. 也可以在连接表中存储已连接用户的用户详细信息,例如向该表添加两个名称字段。这很快,但如果用户名更改(从Facebook检索姓名和电子邮件),则详细信息无效,我需要更新所有条目。
  2. 使用批量获取请求查询每个userId的用户详细信息以读取多个项目。这可能会比较慢,但我总是拥有最新的用户详细信息,不需要将它们存储在连接表中。
  3. 那么什么是更好的解决方案,还是我可能忽略了其他任何优点/缺点?

    修改

    在对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。

    您如何看待该数据库模型?

2 个答案:

答案 0 :(得分:2)

通常,nosql数据库通常与几个假设相结合:

  • 最终的一致性是可以接受的。也就是说,如果在更新期间某些中间答案是对的,那么它在应用程序设计中通常是可以接受的。也就是说,如果爱丽丝成为鲍勃的朋友几秒钟就可以了,如果爱丽丝鲍勃的朋友是#34;那就好了。返回true,而#34;是Bob Alice的朋友"返回false

  • 表现很重要。如果你正在使用nosql,那通常是因为性能对你很重要。它也几乎可以肯定,因为您关心最常发生的操作性能。 (你可能会遇到一些问题,其中一些不常见的操作的性能如此糟糕以至于你无法做到;在这种情况下,nosql通常不是答案)

  • 您愿意减少不常见的操作以提高常见操作的性能。

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

关于您列举的具体选项。

  • 假设性能足以让nosql成为您应用程序的合理解决方案,那么几乎可以肯定的是查询而不是更新您关心的性能。如果您使更新更慢,更昂贵,您可能会很高兴,以便查询可以更快。这就是重点。

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

  • 在每个方向存储朋友行可能是有意义的,因此您只需要一个查询。

  • 将您通常显示在友谊行中重复的朋友列表中的用户信息(如姓名和图片)存储可能是有意义的。请注意,只要名称或图片发生变化,您就需要更新所有这些行。

  • 不太清楚将朋友存储在用户表中是有道理的。这可能会变得很大。此外,保证最终的一致性可能很棘手。考虑如果您正在处理两个用户的更新,会发生什么?友谊在同一时间。一旦尘埃落定,你就不会感到不一致,这一点非常重要。

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

答案 1 :(得分:1)

我建议您在表格中包含以下字段:

  • userId (哈希键)
  • 名称(排序键)
  • 电子邮件
  • connections (逗号分隔或 userId 数组,假设您有多个用户连接)

此结构可确保数据的一致性。