何时使用CouchDB而不是RDBMS

65

我正在考虑使用CouchDB,它相对于关系型数据库具有以下吸引人的特性:

  • 直观的REST/HTTP接口
  • 易于复制
  • 数据以文档形式存储,而不是规范化表格

我知道这不是一个成熟的产品,因此应谨慎采用,但我想知道它是否实际上可以替代关系型数据库(尽管介绍页面说不行 - http://couchdb.apache.org/docs/intro.html)。

  1. CouchDB在哪些情况下比RDBMS(如MySQL)更好选择,例如在可扩展性、设计+开发时间、可靠性和维护方面?
  2. 仍然存在明显需要使用关系型数据库的情况吗?
  3. 这是一种二选一的选择,还是混合解决方案更可能成为最佳实践?
7个回答

48

我最近参加了伦敦的NoSQL大会,现在我认为我更有把握回答原始问题了。我还写了一篇博客文章,还有一些其他好的文章

关键点:

  • 我们已经积累了大约30年的关系型数据库管理知识,因此不应该在仔细考虑之前替换它们;非关系型数据存储不如关系型数据库成熟,因此采用它们固有的风险更大
  • 有不同类型的非关系型数据存储;有些是键值存储,有些是文档存储,有些是图形数据库
  • 可以使用混合方法,例如在社交软件站点中结合使用RDBMS和图形数据存储
  • 文档数据存储(例如CouchDB和MongoDB)可能是最接近关系型数据库的存储,提供一个JSON数据结构,并以层次结构呈现所有字段,避免了必须进行表连接,(一些人可能会认为)这是目前大多数应用程序采用的传统对象关系映射的改进
  • 非关系型数据库支持复制(包括主-主);关系型数据库也支持复制,但可能不如非关系型选项全面
  • 诸如Twitter、Digg和Facebook之类的非常大型站点使用Cassandra,它从基础开始构建以支持群集
  • 关系型数据库可能适用于90%的情况

总之,共识似乎是“谨慎行事”。


2
感谢您的精彩博客文章,很好地总结了一些有价值的观点。 - H6.
我想挑战使用“因为成熟”这一说法。众所周知,旧项目经常是一团糟。那么为什么不用设计良好的新软件呢?我认为ACID合规性是数据存储的重要参数,但即使如此,也可以通过适当的代码策略进行辩论。在关系型数据库管理、扩展和恢复备份方面非常痛苦和烦人,而CouchDB在这方面要容易得多。通常的主要权衡决策是速度和完整性之间的折衷,但随着NoSQL系统的快速发展,这条线变得越来越不清晰。 - Vincent Gerris

27

在有更深入的回答之前,下面是一些 CouchDB 的优点和缺点

优点:

  • 你不需要将数据适应于烦人的高阶规范(normal forms)之一
  • 你可以随时更改你的数据 "模式"(schema)
  • 你的数据将被精确索引以符合你的查询,因此你将在恒定时间内获得结果。

缺点:

  • 你需要为每个查询创建视图,即 ad-hoc 类型的查询 (例如在 SQL 中连接动态 WHERE 和 SORT 查询) 不可用。
  • 你要么有冗余数据,要么就得自己在"客户端"(例如多个字段上对多对多关系进行排序)上实现联接(join)和排序逻辑。

优点或缺点:

  • 创建视图并不像在 SQL 中那样直接,而更像解决一个谜题。这取决于你的类型,是优点还是缺点 :)

1
自从提出这个问题以来,我一直在查看其他资料,并且我认为使用CouchDB的主要好处是它对数据的“真实世界”表示,而不是传统关系型数据库所需的规范化数据结构。有关详细解释,请参见http://books.couchdb.org/relax/intro/why-couchdb。我认为我提出的其他问题的答案尚不可用。 - Andrew Whitehouse

13

CouchDB是多种可用的“键/值存储”之一,其他包括老式的BDB,面向web的PersevereMongoDB和CouchDB,新的超快速的memcached(仅限RAM)和Tokyo Cabinet,以及像Hadoop和Google's BigTable这样的大型存储(MongoDB也声称在该领域有所作为)。

关于键/值存储和关系型数据库都有市场。传统上,大多数关系型数据库被认为是在键/值上面的一层。例如,MySQL曾经使用BDB作为表的可选后端。简而言之,键/值不知道字段和关系,而这些是SQL的基础。

键/值存储通常更容易扩展,这使它们在像Twitter这样爆炸性增长时成为一个有吸引力的选择。当然,这意味着存储值之间的任何关系都必须在您的代码中进行管理,而不是只在SQL中声明。CouchDB的方法是在值部分存储大型“文档”,使它们(大多数情况下)自包含,因此您可以在单个查询中获取大部分所需的数据。许多用例符合这个想法,其他则不符。

我看到的当前主题是,在“Rails无法扩展!”之后,现在许多人意识到这不是关于你的web框架;而是关于智能缓存,以避免尽可能地请求数据库和webapp。那里的新秀是memcached。

像往常一样,这完全取决于您的需求。


8
你讨论了这个问题,但没有试图回答它。 - Seun Osewa
2
CouchDB不是传统意义上的键值存储。Mongo和Couch都是面向文档的数据库。 - maxk

7
这是一个难以回答的问题。因此,我将尝试突出CouchDB可能对您产生不利影响的领域。
Couch用户和开发者邮件列表上人们遇到的最大困难有两个:
- 复杂数据的连接。 - 多步骤Map/Reduce。
Couch Views基本上是独立的。如果您需要聚合/合并/交集一组视图,现在您几乎必须在应用程序层面这样做。有一些技巧可以使用视图整理和复杂键来帮助连接,但这些技巧对于某些类型的数据而言只能有限地发挥作用。这可能对不同的应用程序来说是可行或不可行的。尽管如此,通过重新构造数据结构,很多时候可以减少或消除这个问题。
其他人对这个问题的评论展示了一些适合使用CouchDB的不同类型的数据。
还要记住的另一件事是,很多时候您可能需要组合/合并/交集的数据也是您会在关系型数据库中离线处理的数据,因此在CouchDB中执行相同的操作可能不会有任何损失。
简短回答:我认为最终CouchDB将能够处理您想解决的任何问题。但您对其使用的舒适度可能因开发人员而异。我认为这在某种程度上是主观的。我喜欢使用图灵完备语言查询我的数据,并在应用程序层面保留更多逻辑。您的情况可能会有所不同。

3

Sam,对于CouchDB和一般的基于map或document的数据库,你需要采取另一种方法。你无法定义像唯一性这样的约束条件,但是你可以查询数据来检查该电子邮件地址和登录名是否已被使用。这是正确的方法,你需要改变你的思路。


2

如果我说错了,请帮我纠正。Couchdb 在需要验证文档在多个字段上唯一性的情况下是无用的。例如,无法强制执行验证规则“登录和电子邮件必须同时唯一”,并保持数据的一致状态。您可以在保存文档之前检查此内容,但有些人可能会在您之前推送新的数据,导致数据不一致。


CouchDB确实有强制唯一性的方法。不过这些方法都是在键级别上进行的。如果您需要登录和电子邮件都是唯一的,那么只需从它们中派生文档ID,您就永远无法在数据库中插入重复的登录和电子邮件。这种方法与其他方法不同,但同样有效。 - Jeremy Wall
10
考虑两个键:"User_john_dude@example.net" 和 "User_alex_dude@example.net"。这两个用户拥有相同的电子邮件地址dude@example.net - Sam
选择一个作为“主”唯一键,并将其用于主文档。然后使用另一个键创建一个次要文档。它的唯一其他数据是主键。例如,选择电子邮件作为主键,因此用户名是次要的。创建一个带有键“dude@example.net”的文档和任何其他数据,但尚未设置用户名。如果成功,则创建另一个带有键“john”的文档,并在其中存储“dude@example.net”。如果成功,则它们都是唯一的,您可以更新具有键“dude@example.net”的文档,将用户名设置为“john”。如果失败,请向用户询问不同的用户名。 - Joshua Coady
1
您也可以对用户+电子邮件进行哈希,并将其用作密钥。如果查询返回任何结果,则不唯一。 - gabereal
显然,哈希是正确的方法,但您需要分别对用户和电子邮件进行哈希处理,以确保它们各自是唯一的。 - holdenweb

0

如果您正在处理仅具有浅层数据层次结构的表格数据,则关系型数据库系统可能是您最好的选择。这是关系型数据库系统的主要用途,文档和工具支持非常好。

对于更嵌套的数据,例如XML,文档数据库应该提供更快的数据访问。此外,存储模型更接近数据本身,因此检索应该更加直观。


关系型数据库系统今天支持NoSQL用于非结构化数据和文档。因此,我不确定使用Couchdb的优势是什么。 - greenlitmysql
这个问题已经12年了。 - Dana the Sane

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