30

我一直在关注 NoSql 运动的兴起以及随之而来的文档数据库(如 mongodb、ravendb 等)的普及。虽然有很多我喜欢的东西,但我觉得我不理解一些重要的东西。

假设您正在实现一个商店应用程序,并且您想在数据库中存储产品,所有这些产品都有一个唯一的类别。在关系数据库中,这将通过有两个表来完成,一个产品表和一个类别表,并且产品表将具有一个字段(可能称为“category_id”),该字段将引用类别表中包含正确类别条目的行。这有几个好处,包括不重复数据。

这也意味着,如果您拼错了类别名称,例如,您可以更新类别表,然后将其修复,因为这是值存在的唯一位置。

然而,在文档数据库中,这不是它的工作方式。您完全非规范化,这意味着在“产品”文档中,您实际上将拥有一个包含实际类别字符串的值,导致大量重复数据,并且错误更难以纠正。多想一下,这是否也意味着运行诸如“给我该类别的所有产品”之类的查询会导致结果不完整。

当然,解决这个问题的方法是在文档数据库中重新实现整个“category_id”,但是当我想到这一点时,我意识到我应该只使用关系数据库而不是重新实现它们。

这让我相信我错过了一些关于文档数据库的关键点,导致我走上了这条错误的道路。所以我想把它放到堆栈溢出中,我错过了什么?

4

4 回答 4

18

您完全非规范化,这意味着在“产品”文档中,您实际上将拥有一个保存实际类别字符串的值,导致大量重复数据 [...]

确实,非规范化意味着存储额外的数据。这也意味着更少的集合(SQL 中的表),从而导致数据之间的关系更少。每个单独的文档都可以包含原本来自多个 SQL 表的信息。

现在,如果您的数据库分布在多个服务器上,那么查询单个服务器而不是多个服务器会更有效。使用文档数据库的非规范化结构,您更有可能只需要查询单个服务器即可获取所需的所有数据。使用 SQL 数据库,您的相关数据很可能分布在多个服务器上,从而使查询效率非常低。

[...] 并且错误更难纠正。

也是真的。大多数 NoSQL 解决方案不保证诸如引用完整性之类的事情,这在 SQL 数据库中很常见。因此,您的应用程序负责维护数据之间的关系。但是,由于文档数据库中的关系数量非常少,因此并不像听起来那么难。

文档数据库的优点之一是它是无模式的。您随时可以完全自由地定义文档的内容;您不会像使用 SQL 数据库那样绑定到一组预定义的表和列。

真实世界的例子

如果您在 SQL 数据库之上构建 CMS,您将为每种 CMS 内容类型创建一个单独的表,或者在一个包含通用列的表中存储所有类型的内容。使用单独的表格,您将拥有很多表格。想想你需要的所有连接表,比如每个内容类型的标签和评论。使用单个通用表,您的应用程序负责正确管理所有数据。此外,数据库中的原始数据很难更新,并且在 CMS 应用程序之外毫无意义。

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

建议

如您所见,SQL 和 NoSQL 解决方案都各有利弊。正如大卫已经指出的那样,每种类型都有其用途。我建议您分析您的需求并创建两个数据模型,一个用于 SQL 解决方案,一个用于文档数据库。然后选择最适合的解决方案,同时牢记可扩展性。

于 2010-08-10T07:47:32.200 回答
9

我想说的是,您忽略的第一件事(至少基于帖子的内容)是文档数据库并不是要取代关系数据库。实际上,您提供的示例在关系数据库中确实可以很好地工作。它可能应该留在那里。文档数据库只是另一种以另一种方式完成任务的工具,它们并不适合所有任务。

文档数据库是为了解决这个问题(反过来看),关系数据库并不是解决所有问题的最佳方式。两种设计都有其用途,两者本质上都不比另一个更好。

看看 MongoDB 网站上的用例:http ://www.mongodb.org/display/DOCS/Use+Cases

于 2010-08-09T13:21:41.667 回答
4

文档数据库在您开始时给人一种自由的感觉。您不再需要编写 create table 和 alter table 脚本。您只需在主“记录”中嵌入详细信息。

但过了一会儿,你意识到你被另一种方式锁住了。以您在存储数据时认为不需要的方式组合或聚合数据变得不那么容易了。数据挖掘/商业智能(搜索未知)变得更加困难。

这意味着也更难检查您的应用程序是否以正确的方式将数据存储在数据库中。

例如,您有两个集合,每个集合大约有 10000 条“记录”。现在您想知道“表”A 中存在哪些 ID,而“表”B 中没有。

用 SQL 很简单,用 MongoDB 就更难了。

但我喜欢 MongoDB !

于 2010-08-12T21:32:27.070 回答
0

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

例子:

{'@rid':10:3,'@class':'客户','@ver':3,'name':'Jay','surname':'Miner','发明':['Amiga' ] }

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

从客户那里选择发明的地方不为空

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

于 2010-08-12T15:59:55.143 回答