SQL 与 NoSQL

作者:Daniel Bartholomew

Reuven M. Lerner 在近期 LJ 杂志的“At the Forge”专栏中发表的关于 NoSQL 数据库的文章非常有趣。由于这是企业特刊,我认为有必要回顾一下 Linux 数据库的概况,并特别审视一下 SQL 和 NoSQL 数据库之间正在进行的“ battle”(斗争)。需要声明的是,我在 Monty Program 公司工作,该公司的主要产品是 MariaDB,它是 MySQL 的一个社区增强分支。即便如此,我还是尽可能以开放的心态来探讨这个话题。

在过去一年中,SQL 和 NoSQL 之间的竞争愈演愈烈,以至于有些人预测 SQL 时代即将结束。实际上,这两个阵营在很大程度上是互补的,因为它们旨在解决不同的问题。

缩略语

每当谈到数据库时,就会抛出一堆缩略语,其复杂程度足以让 NASA 为之骄傲。我在本文中经常使用的一些缩略语包括

  • RDBMS:关系数据库管理系统。

  • SQL:结构化查询语言,也用于指代使用 SQL 作为查询语言的数据库。

  • NoSQL:用于指代一类非关系型且不使用 SQL 作为查询语言的数据库。它们或许可以更好地称为分布式数据库管理系统 (或 DDBMS),但目前流行的术语是 NoSQL。

  • ACID:原子性、一致性、隔离性、持久性(参见“什么是 ACID?”边栏)。

  • CAP:一致性、可用性、分区容错性(参见“什么是 CAP?”边栏)。

NoSQL 的理由

那么,NoSQL 数据库的意义何在?首先,它们引入了关于数据库是什么以及可以做什么的新方法(或者说是重新引入了旧方法)。其次,它们是崭新的、酷炫的,而且所有时髦的人似乎都在使用它们。您可以认为 Google 的 BigTable 是启发 NoSQL 运动的数据库。或者,也许是 Amazon 的 S3。它们都是闭源的,但它们足够令人印象深刻,足以启发开源的诠释。

当前的 NoSQL 领域包括 HBase、Cassandra、Redis、MongoDB、Voldemort、CouchDB、Dynomite、Hypertable 以及其他一些。有些遵循 BigTable 的模型,有些遵循 S3 的模型,有些是两者的混合,还有一些正在开辟自己的道路。其中一些项目比其他项目更成熟,但它们都在尝试解决类似的问题。

与传统 RDBMS 中常见的带有列和行的表不同,大多数 NoSQL 数据库都是简单的“键值存储”。进入数据库的每条数据都给定一个键,当您想要取回数据时,您使用该键来获取它。这种简单性是有益的,因为它有助于繁忙的站点实现极低的延迟,即使在高负载下也是如此,当与大量服务器和快速网络配对使用时更是如此。键值模型的简单性也简化了开发。

超越简单地拥有键和值的是所谓的文档数据库。在这种情况下,文档是各种信息字段的集合。每个单独的文档可以具有不同数量的不同长度的字段。如果您有大量的半结构化数据,这些数据库非常有用,并且它们非常适合面向对象的编程模型(例如,您可以将数据库视为对象的存储区域)。

为什么传统数据库用户不喜欢这些新来者?SQLite 的创建者 D. Richard Hipp 在我当地的 LUG 举办的一次演讲中,嘲讽地称 NoSQL 数据库为“后现代数据库”,因为它们不是给您一个明确的问题答案,而是给您“一个意见”或他们的“最佳猜测”。他的目的是要将 NoSQL 数据库描绘成负面形象,对于大多数老派数据库世界来说,NoSQL、非关系型、BASE 模型(参见“什么是 ACID?”边栏)不仅仅是有点异端邪说。

这种异端邪说之所以出现,是因为从历史上看,数据库几乎总是试图实现关系模型并完全符合 ACID 标准。如果您的事务不符合 ACID 标准,或者您的数据库不是关系型的,那么论点就是,您不能称自己为“真正的”数据库。看看 MySQL 与 PostgreSQL 的口水战,就能充分证明这种想法。

然而,问题在于,对于某些用例来说,关系型和 ACID 标准并不是必需的,并且会增加不必要的开销,如果您正在运行一个受欢迎的、流量巨大的网站,您就不希望有这种开销。许多早期的 MySQL 用户都知道这一点,并因选择 MySQL 而不是像 PostgreSQL 这样的“真正的”数据库而受到嘲笑。具有讽刺意味的是,现在 MySQL 已经获得了每个“专家”都说它应该拥有的东西(ACID 事务),但一场新的运动已经开始兴起,声称所有旧的数据库技术实际上都不是必需的。

根据 NoSQL 的拥护者的说法,对于顶级网站来说,必要的是大规模可扩展性、低延迟、按需扩展数据库容量的能力以及更简单的编程模型。根据他们的说法,这些以及其他一些东西是 SQL RDBMS 无法以经济高效的方式提供的。

大多数经典的 RDBMS 最初都是设计在单个大型服务器上运行的。这就是 1970 年代末和 1980 年代初的做法,这种想法一直存在于许多 RDBMS 的设计中。当数据库位于单个服务器上时,CAP 中的 P(参见“什么是 CAP?”边栏)是毫无意义的(服务器要么启动,要么关闭,很少或从不只是部分启动),传统的 RDBMS 主要关注一致性,即 ACID,如果服务器之间进行镜像或使用没有单点故障的硬件,则会加入可用性。

一些 NoSQL 数据库也关注 CAP 的 C 和 A 部分。但与传统的 RDBMS 不同,这些数据库从一开始就被设计为在单个数据中心的数十个、数百个甚至数千个节点上运行。这些数据库的部分分区容错性是通过在多个数据中心之间镜像数据库集群来实现的。这些数据库相对于传统 RDBMS 的优势在于,通过将工作分散到所有这些机器上,即使在存在极高的读取和写入次数时,您也可以实现超低延迟,并且借助所有这些机器,您可以快速分析海量数据。

其他 NoSQL 数据库关注 CAP 的 A 和 P 部分,并且被设计为跨越多个数据中心。与 CAP 原理一致,对于这些数据库来说,强一致性是不可能的。弱一致性对于 RDBMS 老卫士来说尤其是一种异端邪说。相反,这些 NoSQL 数据库实现了最终一致性,即任何更改最终都会复制到整个数据库,但在任何给定时间,单个节点或节点组可能不拥有最新的数据。与关注 C 和 A 的 NoSQL 数据库一样,A 和 P 数据库的重点是低延迟、高吞吐量以及任何其他使网站更具响应性并为用户带来更丰富体验的东西。

除了有时为了可扩展性和延迟而放弃一致性之外,NoSQL 数据库打破传统的另一种方式是它们放弃了关系模型。公平地说,有些数据确实不自然地适合关系模型。这可能是因为数据经常更改形式或大小,或者因为数据完全是非结构化的。

NoSQL 数据库打破传统的最后一个方面是赋予它们名称的东西。它们不使用 SQL。放弃 SQL 的原因通常围绕着它不适合现代面向对象的开发流程,或者在使用 SQL 时存在一些感知到的困难。有时,不使用 SQL 的理由很简单,就是“SQL 烂透了”,但这并不是真正的理由。撇开愚蠢的理由不谈,SQL 语言是为与关系数据库一起使用而设计的,而 NoSQL 数据库大多是非关系型的,因此它们不使用 SQL 是有道理的。

SQL 的理由

那么普通的 SQL RDBMS 呢?它们应该从现役中退役吗?它们是早期时代的遗物吗?没那么快。

首先,在某些用例中,绝对需要 ACID 事务。例如,银行和证券交易所使用的数据库必须始终给出正确的数据。在涉及金钱的情况下,不允许猜测。诚然,没有人真正在意您的最新推文是否需要几分钟才能显示在您的 Twitter feed 中,但对于计费系统或会计数据库来说,情况就不同了。

RDBMS 的另一个优点是它们使用 SQL。这是一种通用语言,如果您需要从一个数据库迁移到另一个数据库,通常您只需对应用程序进行少量更改即可,而且它就可以“正常工作”。诚然,在所有情况下都可能无法实现,这取决于您在应用程序中如何使用或滥用 SQL 查询,但是轻松地在不同的 SQL 数据库之间迁移的基础是存在的,您可以用来与数据交互的工具和库非常丰富且健壮。永远不会存在统一的 NoSQL 标准查询语言或 API,因为每个 NoSQL 数据库都非常不同。

在 NoSQL 方面,唯一共同点是没有共同点。每个 NoSQL 数据库都有自己的一组 API、库和用于与其包含的数据交互的首选语言。使用 RDBMS,可以很容易地使用您最喜欢的任何编程语言以您需要的任何格式获取数据。您对 NoSQL 数据库的选择可能会将您限制为一种或少数几种编程语言和访问方法。

RDBMS 的另一个优势是关系模型。RDBMS 中的 R 可以追溯到 E. F. Codd 在 1970 年 6 月的 Communications of the ACM 杂志上发表的研究。从那时起,它得到了扩展、改进和澄清。数据库的关系模型之所以如此受欢迎,是因为它是一种组织信息的绝佳方式。它与各种各样的现实世界数据存储需求非常吻合,并且在正确规范化后,它是快速且高效的。

在关系模型中,数据存储在带有行和列的表中。例如,地址表可能具有街道名称和号码、城市、邮政编码、州或省份以及国家/地区的列。名称表可能具有给定名称、姓氏、前缀(Dr、Rev、Ms 等)和后缀(Jr、Sr、Esq 等)的列。各个表中的每一行都代表一个单独的地址或名称。

关系部分(参见“关系数据库中的关系是什么意思?”边栏)在您使用键定义哪些地址与哪些名称相关时发挥作用。键是单个行中保证唯一标识该特定行的字段(行和列的交集)或字段组合。对于地址表,您可能有一个来自名称表的键的列。您可以使用此键在地址表中查找仅那些“属于”(通过键)名称表中某个名称的地址。

我的示例非常简单,但当与 RDBMS 中的 ACID 事务结合使用时,您可以获得巨大的能力、灵活性和可靠性。企业几十年前开始使用它们是有原因的,开源 RDBMS 主导 Web 也是有原因的。

那么,Web 呢?许多人反对 RDBMS 的主要论点是它们“不可扩展”,但这根本不是真的。诚然,某些个别 RDBMS 的可扩展性不是很好,或者更难扩展,但这并不意味着每个 RDBMS 都不能扩展。RDBMS 正在每个大型公司中使用。最大的 RDBMS 安装例行处理巨大的流量和 PB 级的数据。

每当流行的网站宣布某个 RDBMS 不符合他们的需求,因此他们正在迁移到 NoSQL 数据库 X 时,这种扩展神话就会被延续并被认可。RDBMS 世界中一些人的观点是,这些迁移在很大程度上不是因为他们使用的数据库在某些基本方面存在缺陷,而是因为它被用于其设计目的之外的方式。打个比方,这就像人们使用平头螺丝刀来拧紧十字槽螺钉,因为它在很大程度上可以完成工作,但现在他们发现最好用真正的十字螺丝刀来拧紧十字槽螺钉,这难道不美妙吗,我们应该扔掉所有平头螺丝刀,因为它们的时代已经过去了,而十字槽螺钉才是未来。

最近一次 SQL 到 NoSQL 的迁移涉及 Digg.com 从 MySQL 迁移到 Cassandra。作为迁移的一部分,Digg 的人们在博客中写了他们是如何使用 MySQL 以及为什么它不符合他们的需求的。其他人则持怀疑态度。Dennis Forbes 在他网站上的一系列帖子(参见“资源”)中质疑 Digg 是否真的需要像 Cassandra 这样的 NoSQL 解决方案。他的主张集中在他认为 Digg 在数据库使用方面非常糟糕,并且硬件不足。在他看来,如果 Digg 只是正确地设计了它的数据库,或者切换到在其服务器中使用 SSD,它就不会有任何问题。他最精彩的一句话是:“许多人使用 NoSQL 的方式就像在汽车时代的开始时发现了马车鞭。” 哎哟。

关系数据库有时可能难以正确设计。您必须深入了解和理解您的数据。但是,当它们被正确设计时,与设计不良的数据库相比,性能可以提高几个数量级。您也不应忽视数据库运行的硬件。数据库喜欢尽可能多的内存和处理能力,而传统的旋转盘式硬盘驱动器长期以来一直是一个限制因素。SSD 的高性能是否预示着 RDBMS 性能的新时代?许多专家说是的。SSD 可能是数据库世界中的游戏规则改变者。

关系型 SQL 数据库已经存在了几十年。它们具有经过验证的可靠性和性能,以及满足 99% 用例的功能集。如果那是您拥有的数据类型,它们甚至可以成为出色的键值数据库。只有极少数公司无法使关系数据库为他们工作。您可能不喜欢听,但根据平均规律,您的公司很可能不是其中之一。

结论

我的建议?不要将 SQL 与 NoSQL 视为非此即彼的问题。选择是好事。存在许多替代方案,因此如果您在使用您选择的数据库时遇到问题,请尝试双方的不同产品并运行您自己的基准测试。

还要研究您如何使用您的数据库。如果数据库是在您创建您的杀手级应用程序或服务时“引导”的,并且它开始给您带来问题,那么您可能在您的麻烦根源处有一个容易解决的设计问题。如果数据库不是您的强项,请咨询专家。RDBMS 已经存在很长时间了,并且有很多专家。

无论您决定做什么,都不要将 NoSQL 视为您逃离 SQL RDBMS 世界的避风港。NoSQL 数据库不是万能药。我问了我的老板,MySQL 的创建者 Monty Widenius,他对整个 NoSQL 与 SQL 的看法是什么。他的回答是:“Non-SQL 为您提供了一把非常锋利的刀,可以解决一组特定的问题。如果您发现 SQL 难以使用,您就不应该尝试 Non-SQL。”

他的基本观点是,如果您不了解 SQL RDBMS,您可能会因为跳入 NoSQL 而最终伤害自己。像 NoSQL 数据库中发现的那些键值存储对于某些类型的数据确实有效,但对于其他类型的数据则根本无效。有必要指出的是,使用并拥护 NoSQL 数据库的公司并没有放弃 SQL RDBMS。他们继续在关键角色中使用它们。

最后,许多 NoSQL 想法都基于旧技术。例如,键值存储已经存在 20 多年了。这一次的新事物是像 map-reduce 这样的东西(有些人声称即使这也不是什么新想法),它可以将工作负载分散到多台计算机上。从这个意义上讲,NoSQL 数据库真的应该被称为分布式 DBMS (DDBMS?)。基本上,是分布式 RDBMS,但没有 R。

无论您如何称呼它们,NoSQL 数据库都在解决 RDBMS 世界中的许多人认为“已解决”的问题。它们只是以不同的方式解决问题,并且它们有不同的需求集。如果这种新旧方法解决了您遇到的问题,那就太好了!另一方面,如果您当前的 RDBMS 正在满足您的需求,则不要觉得自己需要赶时髦。

什么是 CAP?

CAP 定理,也称为 Brewer 定理,最初由 Eric Brewer 在 2000 年 7 月于 ACM 分布式计算原理研讨会上发表的主题演讲中提出。它于 2002 年由 MIT 的 Seth Gilbert 和 Nancy Lynch 正式证明。CAP 定理指出,任何共享数据系统都不可能同时保证以下三个属性:一致性、可用性和分区容错性。

CAP 中的一致性与 ACID 中的一致性不同(那样就太容易了)。根据 CAP,数据库中的一致性意味着,无论何时写入数据,每个从数据库读取数据的人都将始终看到数据的最新版本。没有强一致性的数据库意味着,当数据被写入时,并非每个从数据库读取数据的人都会立即看到新数据;这通常被称为最终一致性或弱一致性。

根据 CAP,数据库中的可用性意味着,无论何时您查询数据库以获取信息,您始终可以期望数据库在那里并做出响应。高可用性通常是通过大量物理服务器充当单个数据库来实现的,方法是通过共享(在各种数据库节点之间拆分数据)和复制(在不同的节点上存储每个数据片段的多个副本)。

数据库中的分区容错性意味着,当数据库的某些部分完全无法访问时,数据库仍然可以读取和写入。可能导致这种情况的情况包括当大量数据库节点之间的网络链接中断时。分区容错性可以通过某种机制来实现,通过该机制, направленные 向无法访问的节点的写入被发送到仍然可以访问的节点。然后,当故障节点恢复时,它们会收到它们错过的写入。在 Cassandra 中,这被称为 hinted handoff。具有良好分区容错性的数据库可以跨越多个数据中心,而分区容错性较弱的数据库基本上被绑定到单个数据中心。

什么是 ACID?

ACID 是衡量您的数据库是否良好的经典标准。数据库中的事务是单个逻辑操作。一个示例是在员工数据库中插入地址或更新电话号码。每个数据库都提供了执行此类操作的方法,但 ACID 对该过程进行了形式化。

原子性意味着事务要么成功,要么失败。如果事务失败,它应该完全失败,并且数据库应该保持在事务开始之前的状态。

一致性意味着数据库在事务之前和之后都处于已知的良好状态。

隔离性意味着事务彼此独立,如果两个事务试图修改相同的数据,则其中一个事务必须等待另一个事务完成后才能开始。

持久性意味着一旦事务完成,即使发生系统故障,事务所做的更改也将持久存在。某种事务日志通常用于此目的。在 MariaDB 和 MySQL 中,这被称为二进制日志。

那么,ACID 的反义词是什么?当然是 BASE(基本可用、软状态、最终一致性)。BASE 是 Dan Pritchett 在 ACM Queue 杂志的一篇文章中创造的一个逆构词,用于描述未实现完整 ACID 模型的数据库,主要区别在于它是最终一致性的。其思想是,如果您放弃一些一致性,您可以获得更高的可用性并大大提高数据库的可扩展性。

关系数据库中的关系是什么意思?

在通常用法中,关系数据库的关系部分指的是(或通常被假定为指的是)表通过键相互关联的方式。但对于真正吹毛求疵的人来说,这实际上是不正确的。此处的“关系”并非指表之间的关系,而是指关系的数学概念,这本质上就是关系数据库所称的表。关系数据库是基于关系模型的数据库。

资源

SQL 数据库

MariaDB: askmonty.org

PostgreSQL: www.postgresql.org

NoSQL 数据库

Cassandra: cassandra.apache.org

CouchDB: couchdb.apache.org

HBase: hadoop.apache.org/hbase

Redis: code.google.com/p/redis

Voldemort: project-voldemort.com

MongoDB: www.mongodb.org

Hypertable: hypertable.org

Dynomite: wiki.github.com/cliffmoon/dynomite/dynomite-framework

BigTable: labs.google.com/papers/bigtable.html

Brewer 的 CAP 定理

Julian Browne 的 Brewer 的 CAP 定理: www.julianbrowne.com/article/viewer/brewers-cap-theorem

CAP 定理: devblog.streamy.com/2009/08/24/cap-theorem

Eric A. Brewer 博士的迈向健壮的分布式系统: www.cs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf

Seth Gilbert 和 Nancy Lynch 的 Brewer 的猜想和一致可用分区容错 Web 服务的可行性 (2002): citeseer.ist.psu.edu/544596.html

E. F. Codd 的 “大型共享数据库的关系数据模型”: www.seas.upenn.edu/~zives/03f/cis550/codd.pdf

其他链接

Dennis Forbes 论软件和技术: www.yafla.com/dforbes

Ian Eure 的展望 Cassandra 的未来: about.digg.com/blog/looking-future-cassandra

Johan Oskarsson 的 NOSQL 汇报: blog.oskarsson.nu/2009/06/nosql-debrief.html

Dan Pritchett 的 BASE:ACID 的替代方案: queue.acm.org/detail.cfm?id=1394128

Martin Kleppmann 的您应该超越关系数据库吗?: carsonified.com/blog/dev/should-you-go-beyond-relational-databases

NoSQL 问答: www.dbms2.com/2009/12/11/nosql-q-and-a

Brian Aker 的 NoSQL 视频: www.youtube.com/watch?v=LhnGarRsKnA

Daniel Bartholomew 在 Monty Program 担任技术作家和系统管理员。他与妻子和孩子们住在北卡罗来纳州,经常可以在 Freenode IRC 上的 #linuxjournal 和 #maria 频道找到他。

加载 Disqus 评论