开源中国

我们不支持 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
收藏  
133
推荐标签: MongoDB 待读

这里有内联的user数据的拷贝。这个是Joe的数据流,而且在最顶级有他的用户数据,包括他的name和URL。紧接着下来是他的数据流,包含有Jane的帖子(post)。Joe喜欢(like)Jane的帖子,所以在Jane的帖子的喜欢者(likes)中,我们有Joe的数据的一个单独的拷贝。

你会明白为什么这样做很有吸引力:所有你需要的数据在你需要的地方已经存在。

你也会同样明白为什么这么做是危险的。更新一个user的数据,就意味着要查找所有他们出现过的活动流,以便在这些不同的地方更新这个数据。这很容易出错,经常导致不一致的数据和奇怪的错误,特别是在处理删除操作的时候。

super0555
 翻译得不错哦!

就没有希望了吗?

在MongoDB中你可以采用另一种方法来解决这个问题,如果你有相关背景经验的话会对此更熟悉。与复制用户数据不同的是,你可以在活动流文档中保存用户的引用。

用这个方法,代替那种在需要的地方将用户数据内联进来的方法,你只需给每个user一个ID。一旦用户具有了ID,我们就只需在之前内联数据的地方保存这个用户的ID。下面的这些新的ID是用绿色标识的。

MongoDB实际用的是BSON IDs(译注:BSON是由10gen开发的一个数据格式,目前主要用于MongoDB中,是MongoDB的数据存储格式),它就像是GUID的字符串形式, 但为了让这些例子便于阅读,这里我只是用了整数。

super0555
 翻译得不错哦!

这消除了我们之前的重复的问题。当用户数据改变时,只有一个文档需要重写。不过我们为我们自己带来了一个新的问题。因为我们将一些数据移到了活动流之外,我们再也不能从一个单独的文档构造一个活动流了。这使得效率降低,复杂性增加。现在构造一个活动流需要 1)检索数据流文档,然后 2)检索所有用户文档以便填写名字和头像。

MongoDB缺少的是SQL风格的join操作,这种操作可以通过写一条查询语句,得到活动流与活动流所引用的所有用户的混合结果。因为MongoDB不具备这种能力,取而代之的是,你必须在你的应用代码中手工做这项混合工作。

super0555
 翻译得不错哦!

简单的非规范化数据

我们回头看一看电视节目(TV shows),电视节目的关系集合没有太多的复杂性。因为关系图中所有的盒子是不同的实体,整个查询可以整合进一个文档,没有重复没有引用。在这个文档数据库中,文档之间没有链接。它不需要join。

然而在一个社交网络中,没有什么能像这样独立存在。在任何时候,只要你看到什么东西看起来像是一个名字或者一幅图像,你就会希望能点击它,看看那个用户,他们的个人资料,以及他们的帖子。TV show应用不是这样运作的。如果你位于巴比伦5(Babylon 5)的第一季第一集,你不会希望点击综合医院(General Hospital)的第一季第一集。

super0555
 翻译得不错哦!

不要链接文档

我们开始在Diaspora代码中手工做这项烦人的MongoDB joins操作时,我们很清楚这只是麻烦的第一个迹象。这个迹象表明我们的数据实际是相互关联的,这个数据结构具有价值,而且我们正在违背文档数据库的基本概念。

不管你是否在复制关键数据(天啊),或者使用引用并在应用代码中执行join操作(天啊天啊),只要文档之间有链接,你就已经超越了MongoDB。当MongoDB爱好者用不同的方式说“文档”的时候,他们的意思是那些你可以在一张纸上打印出来、拿在手里的东西。一个文档可能具有内部结构——标题(headings)、子标题(subheadings)、段落(paragraphs)和页脚(footers)——但这并没有链接到其它文档。它是独立的半结构化数据。

super0555
 翻译得不错哦!

如果你的数据看起来是那样的,你只需文档。祝贺你!对Mongo而言它是一个好的用例。但是如果文档之间链接具有存在价值,那么实际上你拥有的就不是文档。对你来说MongoDB就不是正确的解决方案。当然它也不是社交型数据的解决方案,在那种数据中文档之间的链接实际上是系统中最关键的数据了。

因此社交型数据不是面向文档的。那是否这就意味着它实际上是……关系型的呢?

super0555
 翻译得不错哦!

又是那个词

当人们说“社交数据不是关系型数据”时,并不是他们说的意思。他们的意思是下面两个方面:

1.“从概念上说,社交数据是一个比表集合更大的图谱。”

这绝对是正确的。但是很少有概念自然的提及模式化表是标准化的。我们用结构化表示是因为它行之有效,这样做可以减少冗余,而且我们可以解决它变慢的问题。

yale8848
 翻译得不错哦!

2.“当在非标准化的单文档结构中查询所有社交数据时是很快的。”

这也是绝对正确的。当你的社交数据是按照关系型存储时,你为特定用户取出活动流将要在许多表中查询,并且当表越大速达越慢。然而,我们可以用简单的方式来解决这个问题。那就是缓存。

在牛津早些年的数据库会议中,我曾做过一个这样的报告,我强烈推荐你看看Neha Narula谈论有关缓存的报告。无论如何,缓存让标准化数据存储变得复杂,但行之有效。我也曾看过缓存非标准化的活动流为一个文档结构,比如说MongoDB,它会让检索数据变得更快。但存在缓存失效的问题。

“在计算机学科中有两个头疼的问题:缓存失效和命名” Phil Karlton
他提出缓存失效的问题是很难解决的。Phil Karlton写过SSL版本3、X11和OpenGL,所以他对计算机了解的还是很多的。


yale8848
 翻译得不错哦!

缓存失效作为一个服务

那什么是缓存失效,为什么解决它很难?

众所周知,缓存失效就是缓存数据过期,它需要更新或是替换了。这里有个在网络应用中经常见的例子。我们有个后台存储器,典型的是PostgreSQL或MySQL,前台有一个缓存层,典型的结构是Memcached或Redis.请求读取用户的活动流时直接从缓存拿数据显然要比从数据库拿快的多。

典型的缓存和后台存储安装

yale8848
 翻译得不错哦!

应用的写操作更加复杂。让我们说说两个粉丝都写了一个消息的情况。首先发生的就是(第一部分)这些消息被复制和存储。一旦这些动作完成,后台将进入下一段工作(第二部分)将这些消息放入所有粉丝的活动流缓存中。

这种模式是很常见的。Twitter将近期活动用户的活动流都放入内存缓存中,当有粉丝发送消息时也将这些消息添加到缓存中。甚至是很小应用使用这样的活动流时也是这么做的(看看:7个表联合查询)。

yale8848
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 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的我学到很多
对于文档数据库存储了关系数据不合适的话,关系数据库应用了反范式,那是不是说明这样的数据结构同样不适合关系数据库?

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