关于文档数据库,我是否有所遗漏?

30
我一直在关注NoSql运动的兴起以及像mongodb、ravendb等文档数据库的流行。虽然我喜欢这些东西的很多方面,但我感觉我还没有理解重要的东西。
比如说你正在实现一个商店应用程序,并且你想要将产品存储在数据库中,所有产品都有一个单独且唯一的类别。在关系型数据库中,这可以通过两个表来完成,一个是产品表,另一个是类别表,产品表会有一个字段(可能称为“category_id”),该字段将引用类别表中持有正确类别条目的行。这样做有几个好处,包括数据不重复。
这也意味着,如果你拼错了类别名称,你可以更新类别表,然后就可以修复它,因为那是唯一存在的值所在的地方。
然而,在文档数据库中,情况并非如此。你完全去规范化,也就是说,在“产品”文档中,你实际上需要包含一个保存实际类别字符串的值,导致大量数据重复,错误更难以纠正。再深入思考,这是否也意味着运行查询语句,比如“给我所有属于这个类别的产品”,会导致不具备完整性的结果呢?
当然,解决这个问题的方法是在文档数据库中重新实现整个“category_id”功能,但当我思考到那一步时,我意识到我应该继续使用关系型数据库而不是重新实现它们。
这让我相信我错过了一些关键点,导致我沿着错误的道路前进。所以我想询问 stack-overflow,我错过了什么?

1
我记得 Bill Karwin 说过:“所有的 NoSQL 技术都会无意中重新发明关系模型。”(http://twitter.com/billkarwin/status/10785836470) - Gordon
我看不出关系型数据库和非关系型数据库之间的区别?通常你会在文章中放置类别的文档ID,而不是类别名称。如果你现在输错了类别ID,那么你就完蛋了。但这也可能发生在MySQL中(如果你没有外键)。至少在CouchDB中,你可以编写验证函数来在服务器端防止此类错误。 - ZeissS
4个回答

18
你需要彻底去规范化,即在“产品”文档中,你实际上会有一个值来保存实际的类别字符串,从而导致大量数据重复出现[...]。
确实,去规范化意味着存储额外的数据。这也意味着更少的集合(SQL 中的表),因此导致数据之间的关系更少。每个单独的文档可以包含多个 SQL 表中的信息。
现在,如果你的数据库分布在多个服务器上,查询单个服务器比查询多个服务器更有效率。使用文档数据库的去规范化结构很有可能只需要查询一个服务器就能获得所需的所有数据。对于 SQL 数据库,有可能相关数据分散在多台服务器上,使得查询非常低效。
错误更难纠正也是正确的。大多数 NoSQL 解决方案不保证诸如参照完整性之类的东西,这些在 SQL 数据库中很常见。因此,你的应用程序负责维护数据之间的关系。然而,由于文档数据库中关系的数量非常小,因此并没有想象中那么难。
文档数据库的优点之一是它是无模式的。你完全自由地定义文档内容;与 SQL 数据库中的预定义表和列不同,你不受任何限制。
真实世界的例子
如果你在 SQL 数据库上构建 CMS,你可以为每个 CMS 内容类型单独创建一个表,或者使用通用列的单个表来存储所有类型的内容。对于分别的表,你会有很多表。考虑一下你需要为每种内容类型的标签和评论等事项创建的所有连接表。对于单个通用表,你的应用程序负责正确管理所有数据。此外,数据库中的原始数据很难更新,并且在你的 CMS 应用程序之外相当无意义。

使用文档数据库,您可以将每种CMS内容存储在一个集合中,同时在每个文档中保持强烈的定义结构。您还可以将所有标签和评论存储在文档中,从而使数据检索非常高效。这种效率和灵活性的代价是:您的应用程序需要更多地负责管理数据的完整性。另一方面,与SQL数据库相比,使用文档数据库进行扩展的成本要低得多。

建议

正如David已经指出的那样,SQL和NoSQL解决方案都有优缺点。我建议您分析您的需求并创建两个数据模型,一个用于SQL解决方案,另一个用于文档数据库。然后选择最适合的解决方案,同时考虑可扩展性。


3
哪些NoSQL解决方案提供引用完整性?大多数NoSQL解决方案都不保证引用完整性。 - Kevin Meredith

9
我认为您忽略的最重要的一点(至少根据帖子内容)是文档数据库并不意味着要取代关系型数据库。实际上,您提供的示例在关系型数据库中确实非常有效。它应该留在那里。文档数据库只是另一种以另一种方式完成任务的工具,它们并不适用于每个任务。
文档数据库是为解决问题而设计的(从另一个角度来看),即关系型数据库不是解决每个问题的最佳方法。两种设计都有其用途,没有一种本质上比另一种更好。
请查看MongoDB网站上的使用案例:http://www.mongodb.org/display/DOCS/Use+Cases

5
我理解你的意思,但是像Facebook、Digg和Reddit这样使用Cassandra的网站,尽管它们具有高度关系型数据结构,但这并不似乎是一个完整的答案。我的意思是,即使在MongoDB的网站上,它的推荐用途之一就是CMS,这确实有我所描述的精确类型的场景。出于多种原因,我不会切换到文档数据库,但我真的想了解其优势。我非常喜欢文档数据库的想法,并能看到许多潜在用途,但首先想要掌握基础知识。 - Josh

4
一个文档型数据库在开始时给人一种自由的感觉。你不再需要编写创建表和修改表的脚本,只需将细节嵌入主记录中。
但是过了一段时间后,你会意识到你被锁定在了另一种方式中。以一种你在存储数据时没有考虑到的方式组合或聚合数据变得更加困难。数据挖掘/商业智能(搜索未知)也变得更加困难。
这意味着检查你的应用程序是否以正确的方式将数据存储在数据库中也变得更加困难。
例如,你有两个包含大约10000个“记录”的集合。现在你想知道哪些ID存在于“表”A中,而不存在于“表”B中。
使用SQL很容易,但在MongoDB中则更加困难。
但我喜欢MongoDB!!

0

OrientDB,例如,支持无模式、有模式或混合模式。在某些情况下,您需要约束、验证等,但您需要灵活地添加字段而不影响架构。这是一种混合模式。

示例:

{ '@rid': 10:3, '@class': 'Customer', '@ver': 3, 'name': 'Jay', 'surname': 'Miner', 'invented': [ 'Amiga' ] }

在此示例中,“name”和“surname”字段是必填的(通过在架构中定义它们),但“invented”字段仅为此文档创建。您的应用程序不需要知道它,但您可以针对它执行查询:

SELECT FROM Customer WHERE invented IS NOT NULL

它将仅返回具有“invented”字段的文档。


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