文档数据库与关系型数据库的优缺点比较

80

我一直在尝试看看能否使用基于文档的数据库(在本例中为CouchDB)来满足一些需求。这里有两个通用的要求:

  • 对具有某些字段的实体进行CRUD操作,其中该字段具有唯一索引
  • 类似于eBay的电子商务Web应用程序(更好的描述请参见此处)。

我开始认为,基于文档的数据库不是最好的选择来解决这些要求。此外,我无法想象出文档型数据库的用途(也许我的想象力太有限了)。

您能否解释一下,当我尝试为这些需求使用文档导向数据库时,是否是在“要梨子还是要榆树”?


2
"从榆树上摘梨"意为不可能的要求。(Jason的链接已失效。) - Dennis
6个回答

39
  • 你需要以文档为中心的方式思考如何处理应用程序。如果你只是试图复制在关系型数据库中建模问题的方式,那么你将会失败。你可能还需要做出不同的权衡。请记住,CouchDB 的设计假定您将拥有一个活跃的集群,其中许多节点可能随时会失效。那么,当数据库节点从其下方消失时,你的应用程序要如何处理它呢?
  • 一种思考方式是想象你没有任何计算机,只有纸质文件。如何使用传递的纸张创建高效的业务流程?如何避免瓶颈?如果出现问题怎么办?
  • 另一个角度是事件一致性,在这种情况下,最终状态将会达成一致,但在某个时间段内可能会不一致。这在关系型数据库领域是无法接受的,但在现实世界中却非常普遍。经典的事务示例是从银行账户之间转移资金。在现实世界中,这是如何实现的——通过单个原子事务还是通过不同的银行相互发放信用和借记通知?写支票会发生什么?
  • 因此,让我们看看你的例子:
  • 带有一些字段的实体的 CRUD 操作,其中某些字段具有唯一索引。
  • 如果我正确理解了 CouchDB 的术语,你希望拥有一个文档集合,在这些文档中,某个命名值在所有这些文档中都是唯一的?这种情况通常是不支持的,因为文档可能会在不同的副本上创建。
  • 因此,我们需要看看现实世界的问题,并尝试对其进行建模。你真的需要它们是唯一的吗?你的应用程序是否能够处理具有相同值的多个文档?你需要指定唯一标识符吗?你能够以确定性的方式做到这一点吗?需要这样的独特顺序标识符的常见场景是需要一个唯一的顺序标识符。在复制的环境中,这很难解决。事实上,如果唯一 ID 要求与创建时间严格顺序排列,那么如果您需要立即获得 ID,则这是不可能的。你需要至少放宽其中的一个约束。
    • 像eBay一样的电子商务Web应用程序

    我不确定在此处添加什么,因为您上次在该帖子中发表的最后一条评论是“非常有用!谢谢”。是否还有某些方法未涵盖到导致您遇到问题?我认为MrKurt的答案已经很充分了,我只是增加了一个小优化,可以减少争用。


    使用UUID作为分布式、共享无状态、全局唯一标识符怎么样?在文档数据库领域中,人们常常这样做吗? - Paul Legato
    @Tim Lovell-Smith + kerrr +1 我喜欢与纸质文档进行真实世界比较的想法。 :) 很好地指出了CouchDB需要/假定集群化的问题。一致性不总是保证的这一点也很好。对于我作为关系型数据库支持者来说,这读起来像是(当然还有其他规则):“如果一致性至关重要,请使用关系型数据库”。对吗?(注:我目前正在启动一个新项目,我想决定是否使用NoSQL或RDB。) - try-catch-finally

    14

    是否需要对数据进行规范化?

    • 需要:使用关系型数据库。
    • 不需要:使用文档型数据库。

    13
    我知道你很久以前就已经回答过这个问题了,但我还是想问一下... 什么情况下需要进行规范化? 规范化不是一个选择/最佳实践吗? - Matt Grande
    1
    @Matt,数据规范化只是一种工具。你规范化数据的程度是数据库设计工作和一致性维护工作之间的权衡。 - isekaijin
    5
    我不认为这是一种区分使用哪种数据库模型的好方法。在关系型和文档型数据库中,规范化都是不可避免的。 我的直觉是,交易规模更有可能是有效的区分因素。 - Munhitsu
    在这里,规范化是什么意思?如果我正确理解规范化作为一种手段,那么你的回答似乎不完整... - Tim Lovell-Smith
    这已经是我第二次读到这个经验法则了(即查看规范化的需求)。但对于我这样的关系型数据库支持者来说,不断尝试理解下一个项目应该使用文档型数据库还是关系型数据库,这个“规则”并没有什么帮助,因为如果我愿意,我可以设计我的关系型数据库非常不规范化(一些工程师甚至从性能角度推荐这样做)。 - try-catch-finally

    8
    我和你有同感,我目前非常喜欢CouchDB,认为整个函数式风格很棒。但我们何时开始认真地将其用于应用程序呢?我的意思是,是的,我们都可以开始极快地开发应用程序,无需担心正常形式被抛在一旁而不使用模式。但是,用一个词来形容,“我们站在巨人的肩膀上”。使用关系型数据库以及规范化和使用模式是有充分理由的。想到没有格式的数据,我的老oracle头脑一片混乱。
    CouchDB让我印象最深刻的是复制和版本控制系统的配合。
    过去一个月里,我一直努力理解CouchDB的存储机制,它似乎使用B树,但不是基于正常形式存储数据。这是否意味着它非常聪明,意识到数据的某些部分被复制,所以只需将指针指向此B树条目?
    到目前为止,我正在考虑XML文档、配置文件、资源文件流式传输到Base64字符串等方面。但是我会将CouchDB用于结构化数据吗?我不确定,对此任何帮助都将不胜感激。
    它可能对存储RDF数据甚至自由形式的文本有用。

    6
    一种可能的方法是拥有一个主关系型数据库,存储可以通过其ID检索的项目定义,以及一个文档数据库,用于描述和/或规格说明这些项目。例如,您可以拥有一个带有以下字段的产品表的关系型数据库:
    • 产品ID
    • 描述
    • 单价
    • 批量大小
    • 规格
    而那个规格字段实际上将包含对具有技术规格的文档的引用。这样,您就可以兼顾两方面的优点。

    2
    SQL Server 2008是一个可以同时使用FILESTREAM数据类型的数据库示例。 - John Saunders
    哇,太棒了!(我从未使用过SQL Server 2008。) - isekaijin
    仅仅能够存储一个松散的“文件”或文件并不意味着它是一个面向文档的数据库系统。真正的面向文档的数据库系统提供了对文档进行索引和有效处理的功能。 - Tim Lovell-Smith
    如果有任何结构,最好利用关系型数据库(或者更好的是范畴论数据库:http://math.mit.edu/~dspivak/informatics/talks/CTDBIntroductoryTalk)来充分利用。我所倡导的是在数据的结构化和非结构化部分之间建立清晰的界限。 - isekaijin
    @TimLovell-Smith 怎么做呢?你提到了“索引和处理文档的功能”。索引是结构,因此,正如我所说的那样,“最好利用关系数据库来获得最大的收益”,即使文档的实际内容并非如此。 - isekaijin
    这种混合解决方案是我在阅读问题中提到的唯一ID约束时所考虑的。 “为什么不只是将私有Web服务绑定到序列生成器上?”但是越来越多的是倾向于...“为什么不将JSON存储在关系数据库中...”我认为现在大多数主要关系数据库都已经或即将支持它(尽管我只检查了Postgres)。即使不支持,也有许多其他自由格式数据类型可用于此目的,但只是无法验证JSON。 - jm0

    4

    基于文档的数据库最适合存储文档。Lotus Notes是常见的实现方式,Notes电子邮件就是一个例子。对于您所描述的电子商务、CRUD等,关系型数据库更适合设计用于存储和检索被索引的数据项/元素(而不是文档)。


    10
    我不同意。文档数据库的主要用途并不是存储文档,而是用于存储分层的数据(JSON 或 XML 格式)。例如,在 MongoDB 中可以对嵌套的 JSON 字段和 JSON 数组建立索引。虽然 MongoDB 也可以存储文档(文件)(通过 GridFS),但即使无法在 MongoDB 中存储文档(文件),它仍然很有用。我认为 MongoDB 应该称为 JSON 数据库而不是文档数据库。 - Theo
    1
    根据维基百科关于“面向文档数据库”的条目,使用XML、YAML或JSON进行信息存储具有类似于面向文档数据库的优点,但它们并不是同一回事。文档数据库最初是为存储文档而设计的。如果您将其用于其他数据,您将无法获得最佳性能/使用率,就像在关系型数据库中存储文档一样。这种情况经常发生。人们在文档数据库中存储关系数据,然后抱怨文档数据库有多糟糕。如果您滥用它们,那么是的。 - Jim Anderson
    1
    维基百科条目http://en.wikipedia.org/wiki/Document-oriented_database已经更新,值得一看以确认文档导向数据库确实不仅仅是实际文档的文件柜。 - Zsolt Török
    有趣。看起来面向文档的数据库在最近几年已经“进化”,超出了我最初认为它们应该具备的功能。 - Jim Anderson

    2

    关于CRUD操作:整个REST范式可以直接映射到CRUD(或反之亦然)。因此,如果您知道可以使用资源(通过URI可识别)和一组基本操作(即CRUD)来建模您的需求,则可能非常接近基于REST的系统,这是许多面向文档的系统提供的开箱即用功能。


    1
    我认为仅将CRUD与REST进行比较并不足以考虑使用面向文档的数据库。还有很多其他因素需要考虑,REST<>CRUD只是其中的一小部分。 - igorsantos07
    1
    我点赞了这篇文章,因为它似乎间接地提到了所谓的“对象关系不匹配”(参见http://blogs.tedneward.com/post/the-vietnam-of-computer-science)。 - Tom Russell

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接