Facebook 类型社交网络的 NoSQL 数据库结构
Posted
技术标签:
【中文标题】Facebook 类型社交网络的 NoSQL 数据库结构【英文标题】:NoSQL Database Structure for Facebook type social network 【发布时间】:2019-02-26 12:32:32 【问题描述】:对于 Facebook 类型的社交网络应用程序,需要高性能的数据库结构,以便将数据存储在 Firebase(Cloud Firestore) (NoSQL) 中。
要存储的数据:
- Userinfo (name, email etc)
- Friends
- Posts
- Comments on posts.
关于查询性能(如果数据库变得庞大),我对以下两种数据库结构感到困惑。
(参考:C_xxx 是 Collection,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
结构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 -> 更好的性能?
更少的嵌套 -> 更好的性能?
一个集合下的AllPosts -> 查询慢?
或者如果你能推荐一个更好的模型,那也很棒。
【问题讨论】:
嘿,到底什么最适合你?你介意发布数据结构吗?这将非常有帮助。 【参考方案1】:在 Firebase 中,经验法则是将单独的实体类型保存在单独的分支中。这一点尤其重要,因为:
(注意:这里的firebase是firebase实时数据库)
-
Firebase 始终加载完整的节点,并且
一旦您授予用户对某个节点的读取权限,他们就可以访问该节点下的所有数据。
例如,在您的第一个数据结构中,要加载朋友列表,您必须加载所有朋友的所有帖子,以及所有这些帖子上的所有 cmets。如果您只想显示朋友姓名列表,那么这比严格需要的数据要多得多。
在您的第二个数据结构中,您离您更近了一步。现在你可以先加载朋友的名字,然后加载他们的帖子。
但即使在这种结构中,您也会遇到同样的问题。如果您想显示一个朋友(或所有朋友)的帖子标题列表,您将不得不加载整个帖子和所有 cmets。这再次比显示帖子标题列表所需的数据多得多。因此,您肯定也希望将 cmets 存储在单独的***列表中,使用帖子的相同键来识别和分组它们。
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
现在,如果您想显示帖子及其 cmets,则必须读取两个节点。如果您对多个帖子执行此操作,您最终将获得大量读取,以基本上执行与 SQL JOIN
等效的 NoSQL。这是很正常的,它本质上是一个客户端连接,它并没有你想象的那么慢,因为Firebase pipelines the requests。
关于这类数据建模的更多介绍,我推荐:
这篇文章在NoSQL data modeling Firebase 博文Denormalization is normal 这个视频系列Firebase for SQL developers这些对之前问题的回答:
Many to Many relationship in Firebase How would you model a collection of users and friends in Firebase? Firebase data structure and url https://***.com/questions/16421179/whats-the-best-way-of-structuring-data-on-firebase/16423051?s=2|19.0394#16423051 https://***.com/questions/30693785/how-to-write-denormalized-data-in-firebase/30699277?s=3|18.5624#30699277 https://***.com/questions/43830610/how-to-denormalize-normalize-data-structure-for-firebase-realtime-database/43832677?s=5|16.2022#43832677【讨论】:
非常感谢您抽出宝贵时间给出详细的答复。现在我对 Firebase 和 DB 结构有了更好的了解。 弗兰克,你提到 Firebase 总是加载整个节点,但是这篇文章 (***.com/questions/46875966/…),它说 firebase 不加载子集合!所以在我的问题中,在结构 1 中,如果我阅读 /C_AllData/以上是关于Facebook 类型社交网络的 NoSQL 数据库结构的主要内容,如果未能解决你的问题,请参考以下文章
用户操作,如社交网络 facebook、myspace,所有大的