1.3 数据模型
数据模型可能是开发软件最重要的部分,它们不仅对软件的编写方式,而且对如何思考待解决的问题有着深远的影响。数据模型是一个描述数据、数据联系、数据语义以及一致性约束的概念工具的集合,采用何种数据模型,往往也意味着系统架构设计的确定。数据模型的发展历史可谓波澜壮阔,它在数学理论的发展与应用程序(应用场景)的需要下不断演变。本节将介绍关系模型、文档模型和图状数据模型三种目前常用的数据模型,分析它们在不同使用场景下的优劣。
关系模型最早于1970年被Edgar Codd提出。关系模型在提出时仅作为理论研究,后演变出应用于关系数据库的SQL而被人们广泛接受,当时很少人能想到其能如此成功地主导数据模型后来二三十年的发展。进入21世纪,数据多样化的表现形式促进了NoSQL和文档数据库的出现,人们对谁才是表示数据关系的最佳模式的争论一度再起:强数据关系模式(关系模型)真的是各种场景的最优选吗?文档模型再次得到众多关注。如今,社交网络的兴起使多对多的数据结构无处不在,海量数据之间复杂的数据关联愈发涌现,人们再次寄希望于数据模型的优化,一个很自然的想法是将数据模型建模为图模型。实际上,近年来风头正盛的文档、图状等数据模型并非新鲜事物,读者在阅读完本节后应思考数据模型的发展与选择某种数据模型的原因。
1.3.1 关系模型
用于数据库管理的关系模型(relational model)是基于谓词逻辑和集合论的一种数据模型,其目标是将实现细节隐藏在更简洁的接口后面。以关系模型作为基础发展出来的SQL,如今已是最著名的数据模型。我们在图1-6中使用一个教师关系、课程关系的例子来具体说明关系模型,关系模型简洁地表示了教师与课程之间的关系。
在基于关系模型的SQL中,关系指代表(table),元组指代行,属性指代列。用关系实例表示一个关系的特定实例,也就是所包含的一组特定的行。由于关系是元组的无序集合,因此元组在关系中出现的顺序是无关紧要的。对于关系的每个属性,都存在一个允许取值的集合,称为该属性的域(domain)。
图1-6 关系模型举例
在使用了关系模型的数据库管理系统中,关系的概念对应于程序设计语言中变量的概念,关系模式的概念对应于程序设计语言中类型定义的概念。关系模式由属性序列及各属性对应域组成。我们可以认为:对于数据的格式,关系模型只做出了关系(表)只是元组(行)的集合,仅此而已。没有复杂的嵌套结构,可以读取表中的任何一行或者所有行,图1-7描述了概念模型(数据库设计人员和用户之间进行交流的语言)到关系模型的转化过程。
图1-7 概念模型到关系模型的转化过程
关系数据库管理系统(RDBMS)和SQL,从20世纪80年代起就作为工具被广泛用于存储、查询具有某种结构的数据。在作为数据存储和查询的主要技术的道路上,关系模型也曾遇到许多竞争技术的挑战,网络模型和层次模型就是其中两个主要竞争技术。
层次模型的一个典型应用是为阿波罗太空计划而发布的IBM信息管理系统(Inform-ation Management System,IMS)。可以认为层次模型是后面介绍的文档模型的前身,前者将所有数据表示为嵌套在记录中的记录,但这种结构在多对多关系、关系之间的关联上存在巨大的局限性。作为层次模型的推广,网络模型的一个记录可能有多个父节点,从而支持多对一和多对多的关系。在网络模型中,记录之间的关系联系使用的不是外键,而是类似C语言中的指针。访问某条记录的唯一方法是选择一条起始于根记录的路径。这条遍历的路径也称为访问路径。这就像一个遍历链表的过程,然而在多对多的关系中,繁多的访问路径成为人们的负担。
相较于上述两种模型,关系模型以三个优点脱颖而出。
●关系模型中的存取路径对用户而言是完全隐蔽的,使程序和数据具有高度的独立性,其数据语言的非过程化程度较高。
●结构简单,实体之间的关系也通过表格的公共属性表示,结构简单明了。
●操作方便,在关系数据模型中操作的基本对象是集合而不是某一个元组。
关系模型的优点也是其缺点的根源。关系数据模型提供了较高的数据独立性和非过程化的查询功能(查询的时候只需指明数据存在的表和需要的数据所在的列,不用指明具体的查找路径),因此加大了系统的负担,查询效率低。此外,关系数据库的查询功能来自查询优化器,它称得上是一个复杂的“怪兽”,开发人员多年来持续投入巨大花费,用以更新迭代查询优化器。
1.3.2 文档模型
进入21世纪,互联网技术迅速发展,数据量迅速膨胀,人类逐步进入大数据时代。大数据给传统的数据管理方式带来了严峻的挑战,关系数据库在容量、性能、成本等多方面都难以满足大数据管理的需求。NoSQL数据库通过折中关系数据库中严格的关系模型的数据一致性管理,在可扩展性、模型灵活性、经济性和访问性等方面,使用文档模型构建的数据库在特定的数据结构下显示出巨大优势。
在文档模型中,数据以文档的形式存储。文件由描述文件实际情况和数据的记录组成。嵌套文档可用于提供有关数据子类别的信息。文档也可以用来表示现实世界的对象。MongoDB是典型的以文档模型为基础的NoSQL数据库。MongoDB支持的数据结构非常松散,将半结构化数据存储为文档,而不是像关系数据库那样在多个表之间对数据进行规范化,每个表都有唯一的固定结构。存储的逻辑结构是一种层次结构,在文档数据库中的文档使用嵌套键值对来提供文档的结构或架构。表1-1对文档数据库(MongoDB) 使用的术语与SQL数据库使用的术语进行了比较。
表1-1 术语对比
一个令人关心的问题是:对比于关系数据模型和文档数据模型,它们各自拥有怎样的优点?下面是我们做出的两点概括性总结。
●支持文档数据模型的主要论点是模式灵活性,由于局部性,它会带来更好的性能,对于某些应用来说更接近应用程序所使用的数据结构。
●支持关系数据模型的主要论点是它在联结操作上的支持、多对一和多对多关系的简洁表达。
大多数文档数据库以及关系数据库中对JSON的支持、都不会对文档中的数据强制模式。关系数据库中对XML的支持通常带有可选的模式验证。无模式意味着可以将任意的键和值添加到文档中,而在阅读时,客户端无法保证文档可能包含哪些字段。文档数据库和关系数据库的灵活性差异在对数据的模式上表现得淋漓尽致。具体来说,文档数据库的具体灵活性体现在其数据结构是遵循读取时模式(数据的结构是隐式的,只有在读取数据时才会解释),而关系数据库的传统方法是写入时模式(模式是显式的,数据库确保所有的书面数据都符合它)。这种不同的设计模式至今仍是一个备受争议的话题,一般来说没有正确或错误的答案。强模式意味着低灵活性,弱模式虽然带来了灵活性的优点,但也导致了数据冗余、关系表示不简洁的问题。下面列举两种能展示文档数据库模式灵活性的情况,请注意这些仅是潜在的适用情况。
●有许多不同类型的对象,将每种类型的对象放在自己的表中是不切实际的。
●数据的结构是由你无法控制的外部系统决定的,并且在任何时候都可能发生变化。
在这两种情况下,有固定的模式可能会比没有伤害更大,而无模式的文档可能是一个更自然的数据模型。但是我们应该承认,在所有记录都具有相同结构的情况下,模式是记录和执行该结构的有用机制。
文档模型下的数据库,由于没有严格的数据模式,可以将任意的键值对添加到文档中,这使其很容易表示数据一对多的关系。随着数据之间的关联增大,如出现多对多关系时,文档模型就变得不那么有吸引力了。通过非标准化来减少对连接的需求是可能的,但是应用程序代码需要做额外的工作来保持非规范化数据的一致性。通过向数据库发出多个请求,可以在应用程序代码中模拟连接,但这也将复杂性转移到应用程序中,而且通常比数据库内部专门代码执行的连接要慢。在这种情况下,使用文档模型可能导致应用程序的代码更加复杂、性能更加糟糕。
支持文档数据模型的主要理由是其模式非常灵活,由于局部的性能更好,对于某些应用程序来说,它更接近于应用程序使用的数据结构。关系模型在join、多对一和多对多关系的场景则表现得更好。实际上,随着时间的推移,关系数据库和文档数据库似乎变得越来越相似,这是一件好事:数据模型是互补的,如果一个数据库能够处理类似于文档的数据,并且在其上执行关系查询,应用程序可以使用最适合其需求的特性组合。我们预测,关系模型和文档模型的混合是数据库未来的一个趋势。表1-2是关系模型与文档模型的对比总结。
表1-2 关系模型与文档模型的对比总结
1.3.3 图状数据模型
我们在前面看到,多对多关系是不同数据模型之间的重要区别特征。如果数据大多数为一对多关系(可以表征为树状数据)或者记录之间没有关系,那么文档模型是最合适的。存在少量的多对多关系时,关系模型也可以进行简单的转换处理。
但是,如果多对多关系在数据中很常见呢?想象一下如今的社交网络的数据构成,随着数据之间的关联越来越复杂,将数据建模转化为图模型会更加合适。
图由两种对象组成:顶点(也称为节点或实体)和边(也称为关系或弧)。在现实世界,很多数据可被建模为图。典型的例子包括:
●社交网络:顶点是人,边是指人与人之间的关系。
●Web图:顶点是网页,边表示与其他页面的HTML链接关系。Google的著名算法PageRank就是在Web图上运行的,用于确定网页的搜索排名。
在上述示例中,图的顶点表示相同类型的事物。然而,图并不局限于这样的同构数据,图更为强大的用途在于提供了单个数据存储区中保存完全不同类型对象的一致性方式。以新浪微博为例,其数据的顶点可以是人、地点、事件、用户的评论等;边可以表示哪些人之间是相互关注(或单向关注)的关系、谁评论了哪个帖子、谁参与了哪个事件等。
有多种不同但相关的方法可以构建和查询图中的数据,本节将讨论属性图模型以及三元存储模型作为后续章节的引导内容。在属性图模型中最著名的图形数据库Neo4j及其提供的声明式查询语言Cypher将会在后续章节中详细讲解。
属性图是指给图数据增加了额外的属性信息。对于一个属性图而言,节点和关系都有标签(label)和属性(property),这里的标签是指节点或关系的类型,如某节点的类型为“用户”,属性是节点或关系的附加描述信息,如“用户”节点可以有“姓名”“注册时间”“注册地址”等属性。属性图是一种最常见的工业级图数据的表示方式,能够广泛适用于多种业务场景下的数据表达。属性图由顶点(vertex)、边(edge)、标签(label)、关系类型和属性组成。顶点也称为节点(node),边也称为关系(relationship)。在图形中,节点和关系是最重要的实体。具体来说,节点包括:
●唯一的标识符。
●出边的集合。
●入边的集合。
●属性的集合。
每个关系包括:
●唯一的标识符。
●边开始的节点(尾部节点)。
●边结束的节点(头部节点)。
●描述两个顶点间关系类型的标签。
●属性的集合(键-值对)。
上述这样的设计,使得给定某个节点,可以高效地得到它的所有入边和出边,从而遍历图,即沿着这些顶点链条一直向前或者向后。通过对不同类型的关系使用不同的标签,可以在单个图中存储多种不同类型的信息,同时仍然保持整洁的数据模型。
三元存储模式几乎等同于属性图模型,只是使用不同的名词描述了相同的思想。在三元存储中,数据以非常简洁的形式存储(主体,谓语,客体),一个例子是:在三元组(小明,爱慕,小丽)中,将对象与关系分割成三组,达到信息记录的目的。在实际中,三元组的主体相当于图中的节点,客体则可能是主体属性的值(此时,谓语是主体属性的键)或者是图中的另一个节点(此时,谓语是图中的边)。
到目前为止,我们讨论了关系模型、文档模型、图状数据模型。文档模型和图状数据模型有一个相似特点,即它们都是“读时模式”,不会对存储的数据强加校验,应用过程中可以更好地适应需求的变化。关系模型的优点在于,可以笨拙地模拟出文档和图模型,所以相对来说适用范围更广。它们在各自的目标领域中都足够优秀,也有各自的优势。正所谓数据的表现是多样的,我们不会给出哪种模型一定比哪种模型好的结论。我们真正关心的是能否在不同的业务场景下正确地选择或组合上述模型。