开源中国

我们不支持 IE 10 及以下版本浏览器

It appears you’re using an unsupported browser

为了获得更好的浏览体验,我们强烈建议您使用较新版本的 Chrome、 Firefox、 Safari 等,或者升级到最新版本的IE浏览器。 如果您使用的是 IE 11 或以上版本,请关闭“兼容性视图”。
为什么你不应该使用 MongoDB - 技术翻译 - 开源中国社区

为什么你不应该使用 MongoDB 【已翻译100%】

标签: MongoDB
oschina 推荐于 4年前 (共 40 段, 翻译完成于 12-12) 评论 36
收藏  
132
推荐标签: MongoDB 待读

多年之后的今天,大家公认社交数据并不是关系型的,如果你把它存储在关系型数据库中,你就错了。

但是,其它方案有哪些呢? 有人说图数据库更自然些,不过这里我不打算介绍它,因为图数据库太过小众而不适合用于生产环境。另外一些人说文档数据库对社交数据来说堪称完美,而且也更为主流化足以投入实际使用。下面,让我们看看为什么人们认为社交数据更适合放在MongoDB里,而不是放在PostgreSQL里。

lwei
 翻译得不错哦!

MongoDB 如何存储数据

MongoDB是一个面向文档的数据库。它把你的数据存储在由独立的文档组成的集合中,而不是像关系型数据库那样,存储在由独立的组成的中。在MongoDB中, 一个文档是一大块JSON数据,没有特定的格式或模式。

比如说,你需要对下列一组关系进行建模。这和来自于Pivotal的一个使用了MongoDB的项目类似,是我见过的最适合于文档数据库的用例。

lwei
 翻译得不错哦!

根元素是电视节目。每个节目有很多季,每一季都有很多片段,每个片段都有很多评论和演员表。当用户进入这个网站后,一般都是直接访问一个特定电视节目的页面。在这个页面里他们可以看到所有的季、所有的片段、所有的评论和所有的演员表。从应用的角度来看,当用户访问一个页面时,我们就将检索所有有关电视节目的信息。

有很多方法可以为此数据建模。在典型的关系型数据存储中,上面的每一个方框就是一个表。你必须有一个叫电视节目的表、一个有外键是电视节目的每一季表、一个有外键是每一季的片段表以及外键是片段的评论表和演员表。所以,要得到电视节目的所有信息,你必须要在5个表中查询。

yale8848
 翻译得不错哦!

我们也可以以这样的数据作为一组嵌套的哈希值进行建模。有关特定电视节目的信息的集合是一个大的嵌套的keyvalue数据结构。 在电视节目里有一个季节的数组,每一个季节是一个hash。 在每个季节里,每一个episodes都是一个hash等等. 这就是Mongo如何建立数据模型的. 每一个电视节目是一个包含我们需要的所有信息的文档。

这是一个电视节目文档的例子, Babylon 5.

它有一些标题的元数据,然后是一个季节的数组. 每个季节本身就是一个带有元数据的哈希数组episodes. 反过来, 每个episode 都有一些reviews和cast_members的元数据和数组。

SimpleBy
 翻译得不错哦!

这就像是一个巨大的分形体数据结构。

集合的集合的集合的集合。就像是个分形体!

所有我们需要的电视节目数据都在一个文档里,所以要检索一次所有信息时是很快的,即使这个文档很庞大。美剧“综合医院”发布了50+季,超过12000集。在我的笔记本电脑上,PostgresSQL查询所有数据得1分钟,而在MongoDB中用一个ID查询时是秒级。

所以,不管怎么说,这个应用对于存储文档模型还是不错的选择。

yale8848
 翻译得不错哦!

好吧,那社交数据又是怎样的?

好的,当你进入社交网站后,映入眼帘的唯一重要页面部分是你的活动流。活动流显示了你所有关注人的信息,这些信息是按最新时间排序的。每一条信息里都是网状结构,比如说图片,喜欢,分享以及评论。

网状结构的活动流看起来和上面提到的电视节目很相似。

yale8848
 翻译得不错哦!

用户有朋友,朋友有帖子,帖子有评论和喜欢,每一个评论有一个评论者,每一个喜欢有一个喜欢的人。这种关系并不比电视节目的复杂。和电视节目一样,当用户登录后,我们就想一次取出所有的数据。此外,在关系数据库中,所有的数据都是规格化的,这就得在7个表中查询才能得到所有数据。

7个表联合查询。啊!如果将每个用户的活动流作为一个大的非标准化的网状结构来存储的话,要比每一次连接查询看起来要好的多。

在2010年时,Diaspora团队做出了这个决定,并深受Etsy有关用文档结构存储文章的影响,尽管当时他们曾公开远离了MongoDB数据存储。同样的,Facebook的Cassandra也曾呼唤要远离关系数据库。Diaspora与时俱进的选择了MongoDB。从他们的信息数据来看,这样的选择是明智的。

yale8848
 翻译得不错哦!

问题可能出在哪?

Diaspora的“社交数据”和TV show的Mongo风格数据之间有一个很重要的不同点,我们在开始时都没有注意到。

TV Show中,数据关系表的每一部分都属于不同的数据类型。TV Show,Seasons,Episodes,Reviews,Cast members,他们各不相同。

但对于“社交数据”,有一部分具有相同的数据类型。事实上,图表中所有绿色部分所表示的都是同一种数据类型----Diaspora users

李孟华
 翻译得不错哦!

每个user具有一些friends,而每个friend可能自身就是一个user。或者说,他们也可能不是,因为这是一个分布式的系统。(我今天只是跳过了那整个层面的复杂性。)同样的,commenters和likers也可能是users。

这种类型的重复性使得要想将活动流正规化到一个单独的文档变得更难。那是因为在你的文档的不同部分,可能引用了相同的概念——在这个例子中,就是相同的user。在活动流中喜欢(like)那个帖子(post)的user,可能也是评论(comment)另一个不同帖子(post)的user。

super0555
 翻译得不错哦!

重复数据重复数据

在MongoDB中我们可以用几种不同的方式来表示它。复制是一种简单的选择。在第一次提交的时候,friend的所有信息都被复制下来并被保存到like,之后在第二次提交的时候,一个单独的副本被保存到comment。这里的好处在于,在你需要数据的任何地方,它都是存在的,而且你仍然可以把整个活动流作为一个单独的文档处理。

这里就是这类完全非规范化的流程文档的样子。

super0555
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(36)
Ctrl/CMD+Enter

ok
题目与示例脱节:通过两个用法错误的失败案例来“反”MongoDB太没说服力了。
写的很好
呵呵,好东西顶起来
"例如,如果你在一个关闭了外接网络而无法访问Facebook和Twitter的国家,你的pod依旧会在本地运行,并和你所在国家内的其他人相连接,即使无法访问外部。"
这是在说明技术选型的重要性
任何脱离正确的应用场景和靠谱的运营的使用都是瞎JB扯淡。
为什么我觉得这不是一篇讨论MongoDB技术博客,而是一篇推广Diaspora的软文?
貌似就说了一句话:MongoDB在无引用的文档存储领域具备很大优势,但是不适用于多引用的场合。

引用来自“带刀的麦兜”的评论

请问楼主 这是什么鸡巴玩意

+1
当你选择一个数据存储,应该了解最重要的事情就是你的数据在哪里,你的数据如何连接,你的数据的商业价值所在。如果你还不知道(这是正常的),那么选择不会画你陷入了困境的数据存储。推JSON数据到你的数据库听起来很灵活,但真正的灵活性是很容易添加业务需求de 功能。

这句话很深刻.

对创业来说, 先快速做起一级建筑以后有钱了再玩高级的是正确的即时战略思路. 应该先选择自己熟悉的能够控制的,低成本的组合, facebook能崛起和起手用php+mysql分不开. 像ruby+mongodb这种事后发现不对的,有玩火的危险.
怎么理解MongoDB的缓存失效问题?这是说MongoDB不支持完整的ACID事务特性吗?
请问楼主,这是什么鸡巴玩意? 和mongodb有半毛钱关系?
很受用,讲出了md的不擅长部分;强调沟通的重要性。
典型的不明觉厉
一两个失败的案例就推翻mongodb,只能说作者选择错误,并不说明mongodb不行
像这种冗余在一开始的时候就能够预料到。
尼玛 刚买了本书 准备好好学学
受益匪浅,给一直想尝试mangodb的我学到很多
对于文档数据库存储了关系数据不合适的话,关系数据库应用了反范式,那是不是说明这样的数据结构同样不适合关系数据库?

目前来讲文档数据库完全代替关系数据库确实很牵强,我认为文档数据库的重点是无模式,而不是能不能有关联数据
顶部