我已经阅读了基于文档的dbs的描述,例如,如果您愿意,可以将所有评论嵌入与帖子相同的文档中:
{
_id = sdfdsfdfdsf,
title = "post title"
body = "post body"
comments = [
"comment 1 ......................................... end of comment"
.
.
n
]
}
我的情况类似,每个评论可能大到8KB,每个帖子可能有多达30个。
即使将评论嵌入到同一文档中也很方便,我想知道大文档是否会影响性能,尤其是当MongoDb服务器和http服务器在不同的机器上运行并且必须通过LAN进行通信时?
答案 0 :(得分:5)
在其他人之后发布这个答案所以我会重复上面提到的一些事情。请接受第一个合适的答案,而不是这个答案。
那说有几件事需要考虑。考虑以下三个问题:
如果可以回答所有问题,那么您可以嵌入comments数组。在所有其他场景中,您可能需要一个单独的集合来存储您的评论。
首先,您可以以并发安全的方式实际更新和删除注释(请参阅使用位置运算符的更新),但有些事情是您无法做到的,例如基于索引的插入。
将嵌入式阵列用于任何类型的大型集合的主要问题是移动更新问题。 MongoDB为每个文档保留一定量的填充(请参阅db.col.stats().paddingFactor
),以允许它根据需要增长。如果它用完了这个填充(并且它通常在你的用例中),它将不得不移动磁盘上不断增长的文档。这使得更新速度降低了一个数量级,因此是高带宽服务器的一个严重问题。一个相关但但不那么重要的问题是带宽。如果您别无选择,只能查询整个帖子及其所有评论,即使您只显示前10条,也会浪费相当多的带宽,尤其是云环境中的问题(您可以使用$切片以避免其中一些)。
如果你想嵌入这里是基本的操作:
添加评论:
db.posts.update({_id:[POST ID]}, {$push:{comments:{commentId:"remon-923982", author:"Remon", text:"Hi!"}}})
更新评论:
db.posts.update({_id:[POST ID], 'comments.commentId':"remon-923982"}, {$set:{'comments.$.text':"Hello!"}})
删除评论
db.posts.update({_id:[POST ID], 'comments.commentId':"remon-923982"}, {$pull:{comments:{commentId:"remon-923982"}}})
所有这些方法都是并发安全的,因为更新标准是(进程范围)写锁定的一部分。
尽管如此,你可能想要一个专门的收藏品来评论,但这有第二选择。您可以将每个评论存储在专用文档中,也可以使用评论桶,例如每个评论20-30条(详见http://www.10gen.com/presentations/mongosf2011/schemascale)。这有利有弊,因此您可以自行决定哪种方法最适合您想要做的事情。如果你的评论每篇文章的评论可能会超过几百,因为你需要的跳过(N)光标方法的o(N)性能,我会去寻找桶。在所有其他情况下,只需对每个文档方法进行评论。对于其他用例的评论,这也是最灵活的。
答案 1 :(得分:4)
这在很大程度上取决于您想要允许的操作,但单独的集合通常更好。
例如,如果您想允许用户编辑或删除注释,那么将注释存储在单独的集合中是一个非常好的主意,因为这些操作很难或不可能单独表示原子修饰符和状态管理变得痛苦。文档also covers this。
嵌入评论的一个关键问题是你将拥有不同的作家。通常,博客文章只能由博客作者修改。通过嵌入式注释,读者也可以获得对象的写访问权,可以这么说。
这样的代码很危险:
post = db.findArticle( { "_id" : 2332 } );
post.Text = "foo";
// in this moment, someone does a $push on the article's comments
db.update(post);
// now, we've deleted that comment
答案 2 :(得分:2)
出于性能原因,最好避免文档随着时间的推移而变大:
填充因子:
“当你在MongoDB中更新文档时,如果是,则更新就地发生 该文件的规模没有增长。如果文档的大小增加, 但是,它可能需要重新定位到磁盘上才能找到新磁盘 具有足够连续空间的位置以适应新的较大文档。 如果集合具有写入性能,则可能导致写入性能出现问题 移动后的许多索引都需要更新所有索引 文件。“
答案 3 :(得分:1)
如果您总是检索包含所有评论的帖子,为什么不呢?
如果你没有,或者你在查询以外的查询中检索评论(即查看用户页面上所有用户的评论),那么可能不会因为查询会变得复杂得多。
答案 4 :(得分:0)
简短回答:是和否。
假设您正在撰写基于mongoDB的博客。您可以将评论嵌入到帖子中。
原因:查询很简单,您只需执行一个请求即可获得所需的所有数据。
现在,您知道您将获得包含子文档的大型文档。当您需要通过LAN提供服务时,我强烈建议您将它们存储在不同的集合中。
原因:通过网络发送大型文档需要时间。我想,在某些情况下,您不需要每个子文档。
TL; DR:两种变体都有效。我建议你将你的评论存储在一个单独的表格中。
答案 5 :(得分:0)
我正在一个类似的项目中,需要发表文章和评论,让我列出这两个方面的要点:
如果满足以下条件,请保留在单独的文档中: -需要删除帖子的特定评论 -希望在任何帖子上显示最新评论(通常是在博客的边栏中)
如果存在以下情况,请保留在同一文档中: -不需要以上任何一项 -需要在同一查询中获取帖子的所有评论(单独的文档方法将需要从不同的文档中获取评论)