Mongodb:关于性能和架构设计
Mongodb: about performance and schema design
在 MongoDB 中学习了性能和模式设计后,我仍然无法弄清楚当性能是必须的时,我将如何在应用程序中进行模式设计。
假设我们必须让 YouTube 使用 MongoDB 作为其数据库。您将如何制作架构?
选项 1:两个合集(视频合集和评论合集)
优点:添加、删除和编辑评论只影响评论集合,因此这些操作会更有效率。
缺点:检索视频和评论将是对数据库的 2 种不同查询,一种用于视频,一种用于评论。
选项 2:单个合集(嵌入评论的视频合集)
优点:您可以通过一次查询检索视频及其评论。
缺点:添加、删除和编辑评论会影响视频文档,因此这些操作会降低效率。
那你怎么看?我的猜测是真的吗?
和往常一样,答案是视情况而定。根据经验,您应该倾向于嵌入,除非您需要定期自行查询嵌入对象,或者嵌入数组可能变得太大(>~100 条记录)。使用此指南,您需要就您的申请提出一些问题。
您的应用程序将如何访问数据?您是否只打算在与相关视频相同的页面上显示评论?或者你想提供选项来显示给定用户对所有电影的所有评论吗?第一种情况倾向于嵌入(一个集合),而在第二种情况中你可能最好使用两个集合。
其次,您希望每个视频有多少条评论?拿 IMDB 做类比,一个流行视频很容易就会有超过 100 条评论,这意味着您最好创建两个单独的集合,因为嵌入的评论数组会很快变大。我不会太担心应用程序连接的开销,如果您的集合已正确索引,它们通常在速度上与关系数据库中的服务器端连接相当。
最后,用户在最初 post 后多久更新一次他们的评论?如果你像在 Whosebug 上那样在 5 分钟后锁定评论,用户可能不会经常更新他们的评论。在那种情况下,更新或删除视频集合中的评论的开销可以忽略不计,甚至可能超过在单独的评论集合中执行第二个查询的成本。
您应该使用嵌入式以获得更好的性能。您的 I/O 会更少。在最坏的情况下?将文档保存在数据库中可能需要一点时间,但检索它不会花费太多时间。
根据您的应用程序需要,您应该在持久性与读取之间折衷,反之亦然。
因此明智地选择数据库很重要。
作为沙漠中的来电者,不得不说embedding只能在非常特殊的情况下使用:
- 关系是 "One-To(-Very)-Few" 并且可以肯定没有文档会超过此限制。一个很好的例子是 "users" 和 "email addresses" 之间的关系——用户不太可能拥有数百万个地址,甚至人为限制也没有问题:设置用户可以设置的最大地址数不得不说 50 几乎不会造成问题。一个视频可能不太可能获得数百万条评论,但你不想对其强加人为限制,对吗?
- 更新不经常发生。如果文档的大小增加超过某个阈值,它们可能会被移动,因为文档保证永远不会碎片化。但是,文档迁移 昂贵 并且您想阻止它们。
- 基本上,对评论的所有操作都变得更加复杂,因此更加昂贵——这是一个糟糕的选择。吻!
我已经写了an article about the above,其中更详细地描述了各自的问题。
此外,我看不出对视频发表评论有任何好处。要回答的问题是
- 对于给定用户,视频是什么?
- 最新的视频(带有特定标签)是什么?
- 对于给定的视频,有哪些评论?
请注意,此处视频和评论之间的唯一联系是关于 给定视频 ,因此您已经有了 _id
或其他可以肯定识别视频的东西。此外,您不想一次加载所有评论,尤其是当您有很多评论时,因为这会因为加载时间长而降低用户体验。
假设它是 _id
。所以,有了它,你就可以轻松地分页评论了:
db.comments.find({"video_id": idToFind})
.skip( (page-1) * pageSize )
.limit( pageSize )
hth
在 MongoDB 中学习了性能和模式设计后,我仍然无法弄清楚当性能是必须的时,我将如何在应用程序中进行模式设计。
假设我们必须让 YouTube 使用 MongoDB 作为其数据库。您将如何制作架构?
选项 1:两个合集(视频合集和评论合集)
优点:添加、删除和编辑评论只影响评论集合,因此这些操作会更有效率。
缺点:检索视频和评论将是对数据库的 2 种不同查询,一种用于视频,一种用于评论。
选项 2:单个合集(嵌入评论的视频合集)
优点:您可以通过一次查询检索视频及其评论。
缺点:添加、删除和编辑评论会影响视频文档,因此这些操作会降低效率。
那你怎么看?我的猜测是真的吗?
和往常一样,答案是视情况而定。根据经验,您应该倾向于嵌入,除非您需要定期自行查询嵌入对象,或者嵌入数组可能变得太大(>~100 条记录)。使用此指南,您需要就您的申请提出一些问题。
您的应用程序将如何访问数据?您是否只打算在与相关视频相同的页面上显示评论?或者你想提供选项来显示给定用户对所有电影的所有评论吗?第一种情况倾向于嵌入(一个集合),而在第二种情况中你可能最好使用两个集合。
其次,您希望每个视频有多少条评论?拿 IMDB 做类比,一个流行视频很容易就会有超过 100 条评论,这意味着您最好创建两个单独的集合,因为嵌入的评论数组会很快变大。我不会太担心应用程序连接的开销,如果您的集合已正确索引,它们通常在速度上与关系数据库中的服务器端连接相当。
最后,用户在最初 post 后多久更新一次他们的评论?如果你像在 Whosebug 上那样在 5 分钟后锁定评论,用户可能不会经常更新他们的评论。在那种情况下,更新或删除视频集合中的评论的开销可以忽略不计,甚至可能超过在单独的评论集合中执行第二个查询的成本。
您应该使用嵌入式以获得更好的性能。您的 I/O 会更少。在最坏的情况下?将文档保存在数据库中可能需要一点时间,但检索它不会花费太多时间。
根据您的应用程序需要,您应该在持久性与读取之间折衷,反之亦然。
因此明智地选择数据库很重要。
作为沙漠中的来电者,不得不说embedding只能在非常特殊的情况下使用:
- 关系是 "One-To(-Very)-Few" 并且可以肯定没有文档会超过此限制。一个很好的例子是 "users" 和 "email addresses" 之间的关系——用户不太可能拥有数百万个地址,甚至人为限制也没有问题:设置用户可以设置的最大地址数不得不说 50 几乎不会造成问题。一个视频可能不太可能获得数百万条评论,但你不想对其强加人为限制,对吗?
- 更新不经常发生。如果文档的大小增加超过某个阈值,它们可能会被移动,因为文档保证永远不会碎片化。但是,文档迁移 昂贵 并且您想阻止它们。
- 基本上,对评论的所有操作都变得更加复杂,因此更加昂贵——这是一个糟糕的选择。吻!
我已经写了an article about the above,其中更详细地描述了各自的问题。
此外,我看不出对视频发表评论有任何好处。要回答的问题是
- 对于给定用户,视频是什么?
- 最新的视频(带有特定标签)是什么?
- 对于给定的视频,有哪些评论?
请注意,此处视频和评论之间的唯一联系是关于 给定视频 ,因此您已经有了 _id
或其他可以肯定识别视频的东西。此外,您不想一次加载所有评论,尤其是当您有很多评论时,因为这会因为加载时间长而降低用户体验。
假设它是 _id
。所以,有了它,你就可以轻松地分页评论了:
db.comments.find({"video_id": idToFind})
.skip( (page-1) * pageSize )
.limit( pageSize )
hth