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

时间:2018-09-22 08:28:40

标签: database mongodb firebase nosql google-cloud-firestore

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

要存储的数据:

 - Userinfo (name, email etc)
 - Friends
 - Posts
 - Comments on posts.

在查询性能(如果数据库变得庞大)的以下两个数据库结构之间,我感到困惑。

(参考:C_xxx是Collection,D_xxx是document)

结构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

结构2

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

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

以下是我可能想到的几点,如果我错了,请纠正我。

结构1:

是否在结构1中更快地获得了给定用户的所有帖子?由于我们正在查找确切的集合(AllData / {UserID} / Posts /)

由于整个数据库都在一个集合中,因此可伸缩性不好吗?

结构2:

划分的DB->更好的可伸缩性?

分开的DB->更好的性能?

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

一个帖子下的所有帖子->查询缓慢?


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

1 个答案:

答案 0 :(得分:3)

在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

现在,如果要显示帖子及其评论,则必须阅读两个节点。如果对多个帖子执行此操作,则最终将产生大量读取,从而实际上执行了与SQL JOIN等效的NoSQL。这是很正常的事情,它本质上是一个客户端联接,并且它的速度不如您想象的那么慢,因为Firebase pipelines the requests

有关这种数据建模的更多介绍,我建议:

以下问题的答案: