2.1 NoSQL一词的出现

最近,“NoSQL”一词变得非常流行和流行,各种软件解决方案都在这个标志下积极开发和推广。NoSQL 已经成为海量数据、线性可伸缩性、集群、容错、非关系性的代名词。然而,很少有人清楚地了解NoSQL存储是什么,这个词是怎么出现的,它们有什么共同的特点。让我们尝试填补这个空白。

这个词最有趣的地方在于,尽管它在 90 年代末首次使用,但直到 2009 年年中才以现在使用的形式获得了真正的意义。最初,这是一个开放的名称- 由 Carlo Strozzi 创建的源数据库,它将所有数据存储为 ASCII 文件,并使用 shell 脚本而不是 SQL 来访问数据。它与当前形式的“NoSQL”无关。

2009 年 6 月,Johan Oskarsson 在旧金山组织了一次会议,讨论 IT 存储和处理市场的新趋势。会议的主要推动力是新的开源产品,如 BigTable 和 Dynamo。对于会议的亮点,有必要找到一个能够完美融入 Twitter 主题标签的宽泛而简洁的术语。其中一个术语是由来自 RackSpace 的 Eric Evans 提出的——“NoSQL”。该术语仅计划用于一次会议,并没有很深的语义负载,但碰巧它像病毒式广告一样传遍了全球网络,并成为 IT 行业整个方向的事实上的名称。顺便说一句,Voldemort(Amazon Dynamo 克隆)、Cassandra、Hbase(Google BigTable 的类似物)、Hypertable、CouchDB、MongoDB 在会议上发言。

值得再次强调的是,“NoSQL”一词完全是自发的,并没有一个普遍接受的定义或背后的科学机构。这个名称更像是远离关系数据库的 IT 开发向量的特征。它代表 Not Only SQL,尽管有支持者直接定义 No SQL。Pramod Sadalaj 和 Martin Fowler 在他们最近出版的“NoSQL Distilled”一书中试图对有关 NoSQL 世界的知识进行分组和系统化。

2.2 NoSQL数据库的基本特征

所有 NoSQL 几乎没有共同特征,因为许多异构系统现在都隐藏在 NoSQL 标签下(也许最完整的列表可以在 http://nosql-database.org/ 找到)。许多特性是某些 NoSQL 数据库特有的,我在列出时肯定会提到这一点。

1.没有使用SQL

我的意思是 ANSI SQL DML,因为许多数据库尝试使用类似于众所周知的最喜欢的语法的查询语言,但没有人设法完全实现它并且不太可能成功。尽管有传言称有初创公司正在尝试实施 SQL,例如在 hadup(http://www.drawntoscalehq.com/http://www.hadapt.com/)中。

2. 非结构化(schemaless)

意思是,在 NoSQL 数据库中,与关系数据库不同,数据结构不受规范(或者弱类型,如果我们用编程语言进行类比)——您可以在单独的行或文档中添加任意字段,而无需先声明性地更改结构整张桌子的。因此,如果需要更改数据模型,那么唯一足够的操作就是在应用程序代码中反映更改。

例如,重命名 MongoDB 中的字段时:

BasicDBObject order = new BasicDBObject();
order.put("date", orderDate); // this field was a long time ago
order.put("totalSum", total); // before we just used "sum"

如果我们更改应用程序逻辑,那么我们在读取时也会期望有一个新字段。但是由于缺少数据模式,其他已经存在的 Order 对象中缺少 totalSum 字段。在这种情况下,有两种选择可以采取进一步行动。

第一种是爬取所有文档并更新所有现有文档中的这个字段。由于数据量大,这个过程发生时没有任何锁(相当于 alter table rename column 命令),所以在更新期间,已经存在的数据可以被其他进程读取。因此,第二种选择——签入应用程序代码——是不可避免的:

BasicDBObject order = new BasicDBObject();
Double totalSum = order.getDouble("sum"); // This is the old model
if (totalSum  == null)
totalSum = order.getDouble("totalSum"); // This is the updated model

并且当我们重新记录时,我们将以新格式将此字段写入数据库。

没有模式的一个令人愉快的结果是处理稀疏数据的效率。如果一个文档有 date_published 字段,而第二个没有,则不会为第二个创建空的 date_published 字段。这在原则上是合乎逻辑的,但一个不太明显的例子是列系列 NoSQL 数据库,它使用熟悉的表/列概念。但是,由于缺少模式,列不会以声明方式声明,并且可以在用户的​​数据库会话期间更改/添加。这尤其允许使用动态列来实现列表。

非结构化模式有其缺点——除了上面提到的更改数据模型时在应用程序代码中的开销——缺少来自基础的各种限制(非空、唯一、检查约束等),再加上在并行处理不同项目的数据库时,在理解和控制结构数据方面会遇到额外的困难(数据库一侧没有字典)。然而,在瞬息万变的现代世界中,这种灵活性仍然是一种优势。一个例子是推特,五年前,除了推文,它只存储了一些额外的信息(时间、推特句柄和更多字节的元信息),但现在,除了消息本身,还有更多的信息千字节的元数据存储在数据库中。

(以下主要讨论key-value、document和column-family数据库,图数据库可能没有这些特性)

2.3. 以聚合(aggregates)形式表示数据

与关系模型将应用程序的逻辑业务实体存储到各种物理表中以实现规范化目的不同,NoSQL 存储将这些实体作为整体对象进行操作:

此示例演示标准电子商务概念关系模型“订单 - 订单项目 - 付款 - 产品”的聚合。在这两种情况下,订单与位置组合成一个逻辑对象,而每个位置存储一个指向产品的链接及其一些属性,例如名称(为了在检索时不请求产品对象,这种非规范化是必要的一个顺序——分布式系统的主要规则是对象之间的“连接”)。在一种聚合中,付款与订单结合在一起,并且是对象的组成部分,在另一种聚合中,它们被放置在一个单独的对象中。这展示了在 NoSQL 数据库中设计数据结构的主要规则——它必须服从应用程序的要求,并尽可能针对最频繁的请求进行优化。

许多人会反对,并指出在查询不适合聚合结构时尝试对数据进行任意查询时,使用大型的、通常是非规范化的对象会充满许多问题。如果我们将订单与订单行项目和付款一起使用(这就是应用程序的工作方式),但企业要求我们计算上个月售出的特定产品的数量怎么办?在这种情况下,我们不必扫描 OrderItem 表(在关系模型的情况下),而是必须检索 NoSQL 存储中的整个订单,尽管我们不需要太多此类信息。不幸的是,这是在分布式系统中必须做出的妥协:我们不能像在传统的单服务器系统中那样规范化数据,

我试图将两种方法的优缺点分组在一个表中: