我将其分为四个基本组:传统、MPP(大规模并行处理)、列式存储和一种新兴技术称为 NewSQL。
传统
这些是我们多年来常见的数据库。一些供应商可能包括 MySQL、PostgreSQL、MS SQL Server、Sybase、Oracle 数据库等。它们符合 SQL 标准并提供完整的 ACID 事务。也就是说,你可以在平台上直接进行大量的数据转换,并保证不同的人查看相同的数据时会看到相同的值。它们也是关系型的,即不同表中的数据通常会被连接在一起。大多数情况下,这些数据库会在单个节点或网格中的几个节点上运行(有些例外)。这些数据库通常用于处理原子(最低粒度)级别事务的业务应用程序。它们也在处理和存储涉及物理价值的数据时使用。例如,你公司的 ERP 和供应链系统将使用这些数据库来存储数据。正确调整、配置和建模后,它们也可以很好地用作数据仓库解决方案。
MPP(大规模并行处理)
一般来说,提供了与传统数据库大部分相同的功能,但是可以扩展到数百或数千个节点。该领域的供应商包括 Oracle Exadata、Teradata、EMC Greenplum 和 IBM Netezza。这些通常在大型企业中作为数据仓库的核心使用。一些供应商还为 MPP 数据库提供了专门的方法。例如,像 Vertica 数据库、Actian Matrix 和 Sybase IQ 这样的平台在 MPP 解决方案中提供了列式存储(见下文)。SAP HANA 和 Exasol 是主要在内存中操作的 MPP 数据库的例子。
NewSQL
同样,非常类似于 MPP 和传统数据库,因为它们是 ACID 兼容和支持 SQL 标准的,只是这些解决方案倾向于非常依赖或完全依赖内存数据存储。它们也倾向于横向扩展。这与主要使用磁盘作为存储机制的其他解决方案相反。这里的权衡是 NewSQL 倾向于存储更少的数据,因为磁盘可以存储比 RAM 更多的数据。实际上,即使是 MPP 解决方案也倾向于使用磁盘、固态硬盘和内存的混合存储。这些解决方案非常流行用于 OLAP 解决方案,因为它们可以快速对大型数据集进行数据更改。NewSQL 的例子有 Oracle Timesten 和 VoltDB。在某些情况下,数据库供应商正在将这些功能融合到现有的平台中。Oracle Database 12c 允许你将表“固定”到内存中。
列式存储
基本上就像听起来那样,数据是以列的形式存储的。如果你想想传统 SQL 数据库中数据是如何通常存储的,你会有一个包含不同类型数据的单一数据行。以用户表为例,你可能有一个 id、一个名字、姓氏、地址信息、人口统计学等。当数据以行的形式存储在磁盘上时,很难以一致的方式压缩它。而当数据以列而非行的形式存储时,使用同样的用户表例子,所有的 ID 都存放在一处,所有的名字都存放在一处等等。这样可以让数据库大大压缩数据,因为现在相似类型的数据都存放在了一起,从而在查询大量记录时减少了物理磁盘读取量。
权衡之处在于,你选择的列越多,你的查询速度就越慢,因为必须从磁盘读取更多的数据。这与传统的 SQL 形成对比,在传统的 SQL 中,向 SELECT 查询添加更多列通常只对查询性能产生很小的影响。它们也不适合高并发查询的使用场景,因为单个查询将使用大量的可用资源。它们也被设计为批量加载,DML 操作非常缓慢。这使得它们非常不适合 OLTP 类型的工作负载。列式数据库的例子有 MonetDB、Sybase IQ 和 Actian Vector。此外,大多数 MPP 和其他数据库供应商提供了列式压缩的机制。
NoSQL 数据存储
这类数据库如此之多,以至于很难真正对其进行一般性的分类,但我会尝试通过描述五种主要的“类型”来进行分类:键值、文档、图、Elastic Search 和时间序列。NoSQL 数据库的共同点是它们都设计为可以在多个服务器之间水平扩展,使用由“网关”节点管理的索引和分片键。几乎所有 NoSQL 数据存储都是基于这一概念,并应用某种程度的数据结构、索引或存储策略,以进一步为某些使用场景提供特定的优势。
它们通常在需要能够同时读取和写入大量数据的情况下使用。这与传统数据库不同,后者通常只能调整为擅长其中之一(再次强调,这是在非常宽泛的术语下)。值得注意的是,NoSQL 是指这些数据库不使用 SQL 作为查询语言,并不意味着对传统 SQL 的拒绝。
你需要记住的是,没有 SQL 兼容性,大多数这些数据库无法在其引擎内部转换数据。你必须将数据提取到其他地方,编写一些代码,然后将转换后的数据放置到你需要的地方。几乎所有的 NoSQL 数据库也都缺乏 ACID 兼容性,而是依赖于“最终一致性”。从高层次上看,这意味着不同的人查询完全相同的数据可能会看到不同的值。你也无法直接在这些数据库中连接数据。
键值
这些基本上提供了一种非常简单的方法来存储和检索二进制数据。对于每条记录,你定义它的键并存储一个值。通常人们会创建大的编程对象,序列化它们,然后存储起来。这些例子包括 OracleNoSQL 和 Berkeley DB、Dynamo和 Riak。我也把 Cassandra 放在这个组里,但实际上,它在每个值内提供了更多的结构,而不仅仅是一个开放的二进制存储。这可以用于存储类似视频游戏用户状态的东西。
文档存储
这些与键值存储相似,但区别在于值不仅仅是简单的二进制对象,而是数据背后有更多的结构。最常见的是数据以 JSON 格式存储,少数使用 XML。同样,对于每个键,你将检索文档值。文档通常是很大的对象,通常是逐个访问的。这些适用于存储具有一定结构的数据,如法律文件或你网站上的整个在线个人资料。
图形
这与键值和文档存储有所不同,这些数据库旨在创建“图”形式的数据。这基本上意味着你可以定义不同数据点之间非常复杂的关系。你还可以轻松地遍历定义了关系的数据,即使它是许多节点之外的数据。可以将其视为社交网络,其中你有朋友、兴趣、签到、喜欢等,并希望定义这些事物之间的关系然后查询它们。例子包括 Neo4j 和 SPARQL。
弹性搜索
这种类型的 NoSQL 数据库往往因对其用途的误解而受到很多关注。最基本来说,这些数据存储索引“单词”,并提供类似于在 Google 中输入内容的搜索功能。它们非常擅长基于关键字搜索在非常大的分布式数据集中查找东西,这是一种“企业搜索”。创建索引需要前期投入,而且它们并不适合执行大量数据扫描的操作(即:分析工作负载)。例子包括 Apache Solr、Elasticsearch 和 Kibana。
时间序列
这些数据存储基于相同的索引和分片键的基本原理。然而,不同之处在于时间戳总是连接键的一部分。记录仅使用“插入”操作追加。这种平台的主要使用场景是为数据用例提供持久化的数据存储,其中你主要希望以趋势的形式检索数据。例如,具有唯一 ID 的传感器不断流式传输数据。任何给定唯一 ID 的数据都存储在同一节点上,并按最近的时间戳排序。这使得针对特定 ID 在特定时间点或时间范围内检索数据变得高效。许多这样的数据存储还根据时间序列提供了额外的功能,如汇总汇总、基于时间的聚合和视觉趋势分析。例子包括 Druid、InfluxDB 和 OpenTSDB。我也可以强烈认为应该把 HBase 归类到这里。