Facebook 类型社交网络的 NoSQL 数据库结构

ker*_*man 5 database mongodb nosql firebase google-cloud-firestore

对于 Facebook 类型的社交网络应用程序,需要一个高性能的数据库结构,用于在 Firebase(Cloud Firestore) (NoSQL) 中存储数据。

要存储的数据:

 - Userinfo (name, email etc)
 - Friends
 - Posts
 - Comments on posts.
Run Code Online (Sandbox Code Playgroud)

我对以下两个关于查询性能的数据库结构感到困惑(如果数据库变得巨大)。

(参考:C_xxx 是收藏,D_xxx 是文档)

结构 1

C_AllData
    - D_UserID-1
        name: xxxx,
        email: yyy,
        friends: [UserID-3, UserID-4]
        - C_Posts
            - D_PostId-1
                Text: hhh
                Date: zzz
                - C_Comments
                    - D_CommentId-1
                        UserID: 3
                        Text: kkk
                    - D_CommentId-2
                        UserID: 4
                        Text: kkk
            - D_PostId-2
                Text: hhh
                Date: zzz
                - C_Comments
                    - D_CommentId-3
                        UserID: 3
                        Text: kkk
                    - D_CommentId-4
                        UserID: 4
                        Text: kkk
    - D_UserID-2
        name: xxxx,
        email: yyy
        friends: [UserID-5, UserID-7]
        - C_Posts
            - D_PostId-3
                Text: hhh
                Date: zzz
                - C_Comments
                    - D_CommentId-5
                        UserID: 5
                        Text: kkk
                    - D_CommentId-6
                        UserID: 7
                        Text: kkk
Run Code Online (Sandbox Code Playgroud)

结构二

C_AllUsers 
    - D_UserID-1
        name: xxxx,
        email: yyy
        friends: [UserID-3, UserID-4]
    - D_UserID-2
        name: xxxx,
        email: yyy
        friends: [UserID-5, UserID-7]

C_AllPosts
    - D_PostId-1
        UserID: 1
        Text: hhh
        Date: zzz
        - C_Comments
            - D_CommentId-1
                UserID: 3
                Text: kkk
            - D_CommentId-2
                UserID: 4
                Text: kkk
    - D_PostId-3
        UserID: 2
        Text: hhh
        Date: zzz
        - C_Comments
            - D_CommentId-5
                UserID: 5
                Text: kkk
            - D_CommentId-6
                UserID: 7
                Text: kkk
Run Code Online (Sandbox Code Playgroud)

我的问题是这两种方法的优缺点是什么?

以下是我能想到的一些要点,如果我错了,请纠正我。

结构1:

是否在结构 1 中更快地获取给定用户的所有帖子?由于我们要精确定位到确切的集合 ( AllData/{UserID}/Posts/ )

由于整个数据库都在一个集合下,可扩展性不是很好吗?

结构二:

分割数据库 -> 更好的可扩展性?

分割数据库 -> 更好的性能?

更少的嵌套 -> 更好的性能?

一个集合下的所有帖子 -> 查询速度慢?


或者,如果您可以提出更好的模型,那也很棒。

Fra*_*len 11

在 Firebase 中,一个经验法则是将不同的实体类型保存在不同的分支中。这一点特别重要,因为:

(注意:这里firebase是firebase实时数据库)

  1. Firebase 始终加载完整的节点,并且
  2. 一旦您授予用户对节点的读取访问权限,他们就可以访问该节点下的所有数据。

例如,在您的第一个数据结构中,要加载朋友列表,您必须加载所有朋友的所有帖子,以及所有这些帖子的所有评论。如果您想做的只是显示朋友姓名列表,那么这比严格需要的数据要多得多。

在您的第二个数据结构中,您更近了一步。现在你可以先加载朋友的名字,然后加载他们的帖子。

但即使在那种结构中,你也有同样的问题。如果您想显示朋友(或所有朋友)的帖子标题列表,您将不得不加载整个帖子和所有评论。这也是显示帖子标题列表所需的更多数据。因此,您肯定也希望将评论存储在单独的顶级列表中,使用帖子的相同键来识别和分组它们。

C_AllPosts
    - D_PostId-1
        UserID: 1
        Text: hhh
        Date: zzz
    - D_PostId-3
        UserID: 2
        Text: hhh
        Date: zzz
C_AllComments
    - D_PostId-1
        - D_CommentId-1
            UserID: 3
            Text: kkk
        - D_CommentId-2
            UserID: 4
            Text: kkk
    - D_PostId-3
        - D_CommentId-5
            UserID: 5
            Text: kkk
        - D_CommentId-6
            UserID: 7
            Text: kkk
Run Code Online (Sandbox Code Playgroud)

现在,如果要显示帖子及其评论,则必须阅读两个节点。如果您对多个帖子执行此操作,您最终会读取大量内容,从而实质上执行 SQL 的 NoSQL 等效项JOIN。这是很正常的,它本质上是一个客户端连接,它并没有你想象的那么慢,因为Firebase 将请求通过管道传输

有关此类数据建模的更多介绍,我建议:

这些对之前问题的回答:

  • 嘿内核工。我的答案确实基于实时数据库,我一定忽略了 Firestore 标签并提到了集合。对困惑感到抱歉。虽然许多相同的原则适用于 Cloud Firestore,但还是存在一些关键差异。子集合的自动加载是较大的集合之一。在这种情况下,将所有评论移动到单个集合中的一个原因是,如果您有一个用例来查询所有帖子的评论。由于 Firestore(尚)不支持跨多个集合进行查询,因此此用例需要在单个集合中包含所有评论 (3认同)
  • 虽然没有性能差异。Firestore 的性能保证之一是集合的大小对该集合的查询性能没有影响。 (3认同)
  • 非常感谢您抽出宝贵的时间给出详细的答案。现在我对 Firebase 和 DB 结构有了更好的了解。 (2认同)

归档时间:

查看次数:

5790 次

最近记录:

4 年,8 月 前