背景

数据模型可能是开发软件最重要的部分,它们不仅对软件的编写方式,而且还对如何解决问题都有深远的影响。

大多数应用程序是通过一层一层叠加数据模型来构建的。每一层都面临的关键问题是: 如何将其用下一层来表示? 例如:

  1. 作为一名应用程序开发人员,通过实际要求,创建对应的对象以及数据结构。
  2. 当需要存储这些数据结构时,可以采用通用数据模型 (例如JSON或XML文档、关系数据库中的表或图模型) 来表示。
  3. 数据库工程师接着决定用何种内存、磁盘或网络的字节格式来表示上述JSON/XML/关系/图形数据。数据表示需要支持多种方式的查询、搜索、操作和处理数据。
  4. 在更下一层,硬件工程师则需要考虑用电流、光脉冲、磁场等来表示字节。

复杂的应用程序可能会有更多的中间层,基于底层API来构建上层API,但是基本思想相同: 每层都通过提供一个简洁的数据模型来隐藏下层的复杂性。

下文将介绍一系列用于数据存储和查询的通用数据模型,我们将比较关系异型、文档模型和一些基于图的数据模型。我们还将讨论多种
查询语言并比较它们的使用场景。

关系模型与文档模型

SQL

现在最著名的数据模型可能是SQL,它基于Edgar Codd于1970年提出关系模型

数据被组织成关系 (relations) ,在SQL中称为表 (table) ,其中每个关系都是元组(tuples) 的无序集合(在SQL中称为行) 。

NoSQL

NoSQL 含义被解释为“不仅仅是SQL” 。

采用NoSQL数据库有这样几个驱动因素,包括:

  • 比关系数据库更好的扩展性需求,包括支持超大数据集或超高写人吞吐量。
  • 普遍偏受免费和开源软件而不是商业数据库产品。
  • 关系模型不能很好地支持一些特定的查询操作。

对象-关系不匹配

现在大多数应用开发都采用面向对象的编程语言,如果数据存储在关系表中,那么应用层代码中的对象与表、行和列的数据库模型之间需要一个笨拙的转换层

关系映射 (ORM) 框架则减少了此转换层所需的样板代码量,但是他们并不能完全隐藏两个模型之间的差异。

例如采用JSON的形式表示简历

使用关系模型表示简历

可以发现 JSON 比多表模式具有更好的局部性,多表模式需要连接多张表进行查询,而对于JSON,所有相关信息都存在一个地方,一次查询就足够了

所以对于这种一对多的模式,采用树状结构(层次模型)可以很好的表示

多对一与多对多

但是在表示多对一或者是多对多的关系时,就并不适合文档模型,但是对于关系数据库,由于支持连结操作,可以很方便地通过ID来引用其他表中的行

关系模型的优势:

  • 结构简单: 所有数据以元组集合的形式存在,简化了数据处理,易于进行条件查询和数据更新。
  • 查询优化: 关系数据库中的查询优化器自动处理查询执行顺序和索引使用,减轻了开发者负担

查询语言

  1. 查询语言的区别:
  • 命令式查询(如IMS和CODASYL所用):要求程序明确每一步的执行过程,如遍历列表、检查条件等,类似于传统编程语言中的逻辑控制。
  • 声明式查询(如SQL):只需指定想要的结果和必须满足的条件,不需要描述如何达到这个结果。这种方法由数据库的查询优化器自动决定执行策略。
  1. 实现差异的影响:
  • 效率和简洁性:声明式查询因其简洁和直观而更易于编写和维护,尤其在处理复杂的数据结构和大量数据时。
  • 性能优化:声明式查询允许数据库系统优化查询执行,如自动选择使用索引和联结,而命令式查询则固定了数据处理的步骤和顺序。
  1. 适用性与并行化:
  • 命令式查询的限制:固定的执行顺序使得并行化处理变得复杂,不适合现代多核和分布式计算环境。
  • 声明式查询的优势:更适合并行执行,因为它不指定操作的具体步骤,数据库可以自由地安排最有效的执行策略。

MapReduce 是一种介于命令式和声明式查询之间的编程模型,主要用于处理和生成大数据集。这种模型允许开发者通过两个主要的函数 map 和 reduce 来指定如何处理数据。

  • Map 函数:处理输入数据,生成键值对作为中间结果。每个输入元素都由 map() 函数独立处理。
  • Reduce 函数:对所有 map() 函数输出的键值对中具有相同键的值进行合并处理。这通常涉及求和、取平均或其他形式的聚合操作。
  1. 执行环境:MapReduce 通常在分布式系统上运行,允许在多个处理单元上并行执行 map() 和 reduce() 函数,优化处理效率。
    系统自动处理数据的分片和分发,并管理各个节点间的数据流转。
  2. 适用场景:MapReduce 特别适合于需要对大量数据进行复杂处理的任务,比如大规模文本处理、日志文件分析和大型数据集的统计分析。
    它的设计允许灵活地扩展到数百或数千台服务器。
  3. 优点:非常适合大规模数据处理,支持高度并行化操作,能够有效地利用分布式系统的计算资源。
    缺点:编程模型相对固定,不如 SQL 灵活;对于一些简单查询或小数据量处理,可能会显得笨重。

图状数据模型

我们之前看到,多对多关系是不同数据模型之间的重要区别特征。如果数据大多是一对多关系(树结构数据) 或者记录之问没有关系,那么文档模型是最合适的。

但是,如果多对多的关系在数据中很常见呢? 关系模型能够处理简单的多对多关系,但是随着数据之间的关联越来越复杂,将数据建模转化为图模型会更加自然。

图由两种对象组成: 顶点 (也称为结点或实体) 和边 。很多数据
可以建模为图。典型的例子包括:

  • 社区网络
    顶点是人,边指示哪些人彼此认识。

  • Web图
    顶点是网页,边表示与其他页面的HTML链接。

  • 公路或铁路网
    顶点是交叉路口,边表示他们之间的公路或铁路线。

小结

历史上,数据最初被表示为一棵大树(层次模型) ,但是这不利于表示多对多关系,所以发明了关系模型来解决这个问题。 最近,开发人员发现一些应用程序也不太适合关系模型。 新的非关系 “NoSQL” 数据存储在两个主要方向上存在分歧:

  1. 文档数据库的目标用例是数据来自于自包含文档,且一个文档与其他文档之间的关联很少。
  2. 图数据库则针对相反的场景,目标用例是所有数据都可能会互相关联。

所有这三种模型 (文档模型、关系模型和图模型) ,如今都有广泛使用,并且在各自的目标领域都足够优秀。我们观察到,一个模型可以用另一个模型来模拟。例如,图数据可以在关系数据库中表示,虽然处理起来比较策拙。这就是为什么不同的系统用于不同的目的,而不是一个万能的解决方案。

文档数据库和图数据库有一个共同点,那就是它们通常不会对存储的数据强加某个模式,这可以使应用程序更容易适应不断变化的需求。但是,应用程序很可能仍然假定数据具有一定的结构,只不过是模式是显式(写时强制) 还是隐式 (读时处理) 的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
模式的灵活性
文档数据库(如MongoDB)和图数据库(如Neo4j)通常被称为“无模式”或“模式灵活”的数据库。
这意味着它们不强制在数据存储时遵守严格的结构。
相比之下,关系数据库(如MySQL)在创建表时需要定义数据的结构(如字段名、数据类型等),并且所有数据必须符合这个结构。

易于适应变化的需求
由于文档和图数据库的这种灵活性,它们特别适合于需求快速变化的应用场景。
开发者可以随时添加新的数据类型或属性,而无需重新定义整个数据库模式。

数据结构的假设
尽管文档和图数据库在存储时不强制模式,但实际应用中,开发者通常还是会假定数据遵循某种结构。
这种结构不是在数据库层面强制实现的,而是在应用逻辑中处理的。
例如,一个应用可能预期每个文档都会有一个特定的字段,如用户ID或名称,即使数据库本身不要求这样。

显式(写时强制):
这指的是像关系数据库那样,在数据写入数据库时就必须满足预定义的模式。
如果数据结构不符合预期,数据库会拒绝这些数据。
隐式(读时处理):
对于文档和图数据库,模式通常是隐式的,这意味着数据结构的合规性是在读取数据时通过应用程序代码来确保的。
数据库本身在写入数据时不会进行检查。