第9章 结束语

现在,我们已经介绍完了7种数据库,祝贺大家!

我们希望你已经了解了这7种数据库。如果你在项目中使用某一种数据库,我们会很高兴。如果你决定使用多种数据库,就像我们在第8章的结尾看到的,我们会欣喜若狂。我们相信,数据管理的未来在于多持久并存模型(在一个项目中使用多种数据库)——而通用RDBMS世界观的迷雾将随风飘逝。

我们借此机会看一看,所介绍的7种数据库在更大的数据库生态系统中如何结合在一起。从这一点来说,我们已经探索了每一种数据库的细节,并提到了一些共性和差异。我们将看到它们如何为宏大的、正在扩展的全部数据存储可选方案做出贡献。

9.1 类型终极版

我们已经看到,数据库存储数据的方式可以主要分为5种类型:关系型、键-值型、列型、文档型和图型。我们来花点时间,回顾一下它们的区别,看看每种风格适合什么,不太适合什么,也就是说,什么情况下你想使用它们,什么情况下想避免它们。

9.1.1 关系型

这是最常见的经典的数据库模式。关系数据库管理系统(RDBMS),是基于集合理论的系统,实现方式是具有行和列的二维表。关系数据库严格强制使用类型,一般分为数值、字符串、日期和未解释的二进制大对象,但我们看到PostgreSQL提供了一些扩展,如数组和cube。

1.适合

因为关系数据库的结构性质,如果提前知道数据的布局,但是可能不清楚随后你打算如何使用这些数据,那么关系型数据库是合适的。或者,换句话说,你提前为组织的复杂性付出代价,以实现随后的查询灵活性。许多业务问题正好是以这种方式建模的,从接单到出货以及库存到购物车。你可能事先不知道以后将如何查询数据(例如,我们在2月份处理了多少订单?),但数据在本质上是相当规范的,所以强制这种规范性是很有帮助的。

2.不那么适合

如果你的数据是高度可变的或者多层次的,那么关系数据库不是最合适。因为你必须提前指定模式,所以,处理记录与记录之间有很大变化的数据问题将遇到麻烦。假设考虑开发一个数据库来描述所有自然界中的生物。创建你需要考虑到的所有特征的完整列表(hasHair、numLegs、laysEggs等)会很棘手。在这种情况下,你选择的数据库最好对可能的输入有较少的预先限制。

9.1.2 键-值存储库

键-值(KV)存储库是我们介绍过的最简单的模型。KV将简单的键映射到(可能)更复杂的值,就像一个巨大的哈希表。由于它们相对简单,因此这种类型的数据库实现起来最灵活。哈希查找速度快,在 Redis 的例子中就是这样,速度是其主要的关注。哈希查找也容易分布化,所以Riak利用这一事实,侧重于简单管理的集群。当然,它的简单性可能对有复杂的建模需求的数据是个缺点。

1.适合

由于很少或不需要维护索引,键-值存储库往往具有横向的可扩展性,速度极快,或两者兼而有之。它们特别适合于数据相关性不高的问题。例如,在Web应用中,用户的会话数据满足这个标准,每个用户的会话活动会有所不同,并且大部分是与其他用户的活动无关的。

2.不那么适合

往往缺乏索引和扫描功能,如果你需要能够执行数据查询,除了基本的CRUD操作(创建、读取、更新、删除)以外,KV存储库的帮助不大。

9.1.3 列型

列型数据库(又称面向列的数据库,或列系列)与KV和RDBMS存储有许多的相似之处。像键-值存储库一样,值的查询通过匹配键完成。类似于关系数据库,把它们的值分组为零或多列,但是每一行可以填充任意多的数据。不同于前两个数据库,列型数据库按列存储类似的数据,而不是按行存储数据。列的添加很容易,版本控制是小菜一碟,并且对于空值没有存储成本。我们看到了HBase是对这一类型的经典实现。

1.适合

传统上,横向扩展作为列型数据库开发的一个主要的设计目标。正因为如此,它们特别适合于在几十、几百或几千个节点的集群上的“大数据”问题。它们也往往内置支持如压缩和版本控制的功能。一个良好的列型数据存储问题的典型例子是索引网页。网页上有大量的文本(好处来自于压缩),在某种程度上相互关联,并随着时间变化(好处来自于版本控制)。

2.不那么适合

不同的列型数据库有不同的特点,并由此带来不同缺点。但有一件事它们是相同的,那就是,最好基于你打算如何查询数据,设计你的数据库模式。这意味着,你应该预先对如何使用数据而不仅仅是数据将如何组成有一些想法。所以,如果你不能提前定义数据的使用模式(例如,需要快速的自由定义的报表),那么列型数据库未必是最合适的。

9.1.4 文档型

文档型数据库允许每个对象有任意数量的字段,甚至允许对象作为值以任意深度嵌套到其他字段中。这些对象通常用JavaScript对象符号(JSON)表示,MongoDB和CouchDB都是这样,但这绝不是一个概念要求。由于文档型数据库不像关系数据库那样彼此相关,它们比较容易在几个服务器上实现分片和复制,这使得分布式实现相当普遍。MongoHQ倾向于支持建立数据中心,管理Web上庞大的数据集,从而解决可用性问题。而CouchDB则侧重于简单耐用,可用性是通过相当自治的节点的主-主复制得到的。这些项目之间有很高的重叠性。

1.适合

文档数据库适合于涉及高度可变领域的问题。当你事先不知道你的数据看起来究竟像什么样子,文档型数据库是一个不错的选择。此外,由于文档型数据库的性质,它们往往能很好地映射到面向对象编程模型。这意味着在数据库模型和应用模型之间移动数据时,阻抗性不匹配的情况较少。

2.不那么适合

如果你习惯于在高度规范化的关系数据库模式中执行复杂的联接查询,你会发现文档型数据库的功能匮乏。文档型数据库一般应包含大部分或全部正常使用所需的有关信息。因此,在一个关系数据库中,你最好自然地规范化你的数据,以减少或消除可能不同步的副本,而使用文档型数据库,非规范化的数据是常态。

9.1.5 图

图数据库是一个新兴的数据库类型,更侧重于自由解释数据之间的相互关系而不是实际的数据值。作为我们的开源示例,Neo4j在许多社交网络应用中日益普及。不像其他数据库类型将相似的对象划为共同的组,图数据库在形式上更自由——查询包含两个节点共享的边,即在节点之间移动。随着越来越多的项目使用它们,图数据库在简单的社交例子上不断发展,用于更多差异细微的使用场景,例如,推荐引擎、访问控制列表和地理数据。

1.适合

图数据库似乎是为网络应用量身定做的。典型的例子是社交网络,其中节点代表相互之间有各种关系的用户。使用任何其他的类型对这种数据建模,往往难以适应,但图数据库会欣然接受。它们还是面向对象系统的完美匹配。如果可以在白板上建模数据,就可以在图中建模。

2.不那么适合

由于节点之间的高度相互关联,因此图数据库一般不适合网络分区。因为图的快速爬取意味着你不能与其他数据库节点的网络联接,所以图数据库不能很好地向外扩展。可能的情况是,如果你使用图数据库,它会是一个较大系统的一部分,大容量数据存储在其他地方,而在图中只保存关系。

9.2 选择

正如我们在开始时所说的,数据是新的石油。我们坐在一片数据的汪洋大海之上,它是不可用的(一个更露骨的比喻是,现在数据中有很多钱),直到把它提炼为信息。轻松收集并最终存储、挖掘、提炼数据,从你选择的数据库开始。

对于给定的领域数据,决定选择哪个数据库往往比仅仅考虑哪个数据库类型最适合更为复杂。虽然社交图谱似乎显然用图数据库最好,但如果你希望用于Facebook,数据太多,所以不能只选择一个。你更可能会选择“大数据”的实现,如HBase或Riak。这将迫使你选择一个列型数据库或键-值存储库。在其他情况下,虽然你可能会认为关系数据库显然是银行交易的最好选项,但要了解的是,Neo4j也支持ACID事务,这样就扩大你的选择范围。

这些例子足以指出,在选择哪个数据库或哪些数据库最好地服务于你的问题领域时,要考虑的不仅是数据库的类型。作为一般规则,当数据的大小增加,特定数据库类型的容量减小了。面向列的数据存储实现往往用于建立为跨数据中心,并支持最大的“大数据”集合,而图一般支持最小的集合。但是,情况并非总是如此。Riak是一个大型的键-值存储库,用于跨越成百上千个节点的分片数据,而 Redis 的设计目标是运行在一个节点上,可能有几个主从复制或客户端管理的分片。

在选择数据库时,还有几个方面需要考虑,如耐用性、可用性、一致性、可扩展性和安全性等。你必须决定自由定义的查询是否重要,是否 mapreduce 就够了。你是否倾向于使用 HTTP/REST接口,或者你是否愿意需要一个自定义的二进制协议的驱动程序?甚至更小范围的关注可能对你也很重要,如是否存在大量数据加载工具。

为了简化这些数据库之间的比较,我们创建了一个表,即附录A。该表并不是一个详尽的功能列表。相反,它是一个工具,迅速比较那些我们已经介绍过的数据库。请注意每个数据库的版本。这些功能在眨眼间就会变化,所以我们强烈建议对于更新的版本,要慎重检查这些值。

9.3 我们将走向哪里

现代应用的伸缩性问题,现在主要是在数据管理的领域。我们已经达到了应用程序演化的一个点,其中编程语言、框架和操作系统的选择正变得非常便宜和容易,甚至是硬件和运营业务(多方虚拟主机和“云”)也是如此。这些选择基本上变成了小问题,既是必须,也是某种偏好。如果你想在这个时代让你的应用可伸缩,就应该考虑选择哪个数据库或哪些数据库,它很可能是你真正的瓶颈。本书的主要目的,就是帮助你正确地做出这种选择。

虽然本书即将结束,但我们相信它已激起了你对多持久并存的兴趣。接下来是仔细研究引起你兴趣的数据库,或者继续学习其他选择,如Cassandra、Drizzle或OrientDB。

开始动手吧。