第6章数据库设计基础知识
本章主要讨论数据库设计的基本概念和方法。首先介绍数据库的基本概念,包括数据库技术的发展历程以及数据模型、数据库管理系统等基本概念;其次介绍主流的关系数据库概念以及关系数据库设计的基础理论方法;然后介绍数据库设计的基本步骤和方法;最后,介绍新型的 No SQL 数据库的基本概念。
6.1 数据库基本概念
数据 (Data) 是描述事物的符号记录,它具有多种表现形式,可以是文字、图形、图像、声音和语言等。信息 (Information) 是现实世界事物的存在方式或状态的反映。信息具有可感知、可存储、可加工、可传递和可再生等自然属性,信息已是社会各行各业不可缺少的资源,这也是信息的社会属性。数据是信息的符号表示,而信息是具有特定释义和意义的数据。
数据库系统 (DataBase System,DBS) 是一个采用了数据库技术,有组织地、动态地存储大量相关联数据,从而方便多用户访问的计算机系统。广义上讲,DBS 包括了数据库管理系统 (DataBase Management System,DBMS)。
数据库 (DataBase,DB) 是统一管理的、长期储存在计算机内的,有组织的相关数据的集合。其特点是数据间联系密切、冗余度小、独立性较高、易扩展,并且可为各类用户共享。一般主要指的是存储数据的各种物理设备以及数据本身。
DBMS 是数据库系统的核心软件,是由一组相互关联的数据集合和一组用以访问这些数据的软件组成。DBMS 要在操作系统的支持下工作,它是一种解决如何科学地组织和储存数据,如何高效地获取和维护数据的系统软件。其主要功能包括数据定义功能、数据操纵功能、数据库的运行管理和数据库的建立与维护。
6.1.1 数据库技术的发展
数据处理是对各种数据进行收集、存储、加工和传播的一系列活动。数据管理是对数据进行分类、组织、编码、存储、检索和维护的活动。数据管理技术的发展经历了 3 个阶段:人工管理、文件系统和数据库系统阶段。
1.人工管理阶段
早期的数据处理都是通过手工进行的,因为当时的计算机主要用于科学计算。计算机上没有专门管理数据的软件,也没有诸如磁盘之类的设备来存储数据。在人工管理阶段,数据处理具有以下几个特点。
- 数据量较少。数据和程序一一对应,即一组数据对应一个程序,数据面向应用,独立性很差。
- 数据不保存。该阶段计算机主要用于科学计算,一般不需要将数据长期保存,只在计算一个题目时,将数据输入计算机,计算完成得到计算结果即可。
- 没有软件系统对数据进行管理。程序员不仅要规定数据的逻辑结构,而且在程序中还要设计物理结构,包括存储结构、数据存取方法、输入输出方式等。
手工处理数据有两个缺点。
- 应用程序与数据之间的依赖性太强,不相互独立。
- 数据组和数据组之间可能有许多重复数据,造成数据冗余。
2.文件系统阶段
由于大容量的磁盘等辅助存储设备的出现,专门管理辅助存储设备上数据的文件系统应运而生。在文件系统中,按一定的规则将数据组织成为一个文件,应用程序通过文件系统对文件中的数据进行存取和加工。
在文件系统阶段中数据管理的特点如下。
- 数据可以长期保留,数据的逻辑结构和物理结构有了区别,程序可以按照文件名称访问文件,不必关心数据的物理位置,由文件系统提供存取方法。
- 数据不属于某个特定的应用,即应用程序和数据之间不再是直接的对应关系,数据可以重复使用。但是文件系统只是简单地存取数据,相互之间并没有有机的联系,即数据存取依赖于应用程序的使用方法,不同的应用程序仍然很难共享同一数据文件。
- 文件组织形式的多样化,有索引文件、链接文件和 Hash 文件等。但文件之间没有联系,相互独立,数据间的联系要通过程序去构造。
文件系统具有如下缺点。
- 数据冗余 (Data Redundancy)。文件与应用程序密切相关,相同的数据集合在不同的应用程序中使用时,经常需要重复定义、重复存储,数据冗余度大。
- 数据不一致性 (Data Inconsistency)。由于相同数据的重复存储,单独管理,同样的数据可能存在于多个不同的文件中,给数据的修改和维护带来难度,容易造成数据的不一致。
- 数据孤立 (Data Isolation), 即数据联系弱。由于数据分散在不同的文件中,而这些文件可能具有不同的文件格式,文件之间是孤立的,所以从整体上看文件之间没有反映现实世界事物之间的内在联系,因此很难对数据进行合理的组织以适应不同应用的需要。
3.数据库系统阶段
数据库系统是由计算机软件、硬件资源组成的系统,它有组织地、动态地存储大量关联数据,方便多用户访问,它与文件系统重要的区别是数据的充分共享、交叉访问、与应用程序的高度独立性。
数据库系统阶段数据管理的特点如下。
- 采用复杂的数据模型表示数据结构。数据模型不仅描述数据本身的特点,还描述数据之间的联系。数据不再面向某个应用,而是面向整个应用系统。数据冗余明显减少,实现了数据共享。
- 有较高的数据独立性。数据库也是以文件方式存储数据的,但是它是数据的一种更高级的组织形式,在应用程序和数据库之间由 DBMS 负责数据的存取。DBMS 对数据的处理方式和文件系统不同,它把所有应用程序中使用的数据以及数据间的联系汇集在一起,以便于应用程序查询和使用。
数据库系统与文件系统的区别是:数据库对数据的存储是按照同一种数据结构进行的,不同的应用程序都可以直接操作这些数据(即对应用程序的高度独立性)。数据库系统对数据的完整性、一致性和安全性都提供了一套有效的管理手段(即数据的充分共享性)。数据库系统还提供管理和控制数据的各种简单操作命令,容易掌握,使用户编写程序简单(即操作方便性)。
6.1.2 数据模型
数据库的基础结构是数据模型,是用来描述数据的一组概念和定义。数据模型的三要素是数据结构、数据操作和数据的约束条件。
- 数据结构。对象类型的集合,是对系统静态特性的描述。
- 数据操作。对数据库中各种对象(型)的实例(值)允许执行的操作集合,包括操作及操作规则。如操作有检索、插入、删除和修改,操作规则有优先级等。数据操作是对系统动态特性的描述。
- 数据的约束条件。是一组完整性规则的集合。也就是说,对于具体的应用数据必须遵循特定的语义约束条件,以保证数据的正确、有效和相容。
按照不同的数据模型,可以将数据库的发展历史分为 3 个阶段。
1.层次和网状数据库系统
层次模型采用树形结构表示数据与数据间的联系。在层次模型中,每个结点表示一个记录类型(实体),记录之间的联系用结点之间的连线表示,并且根结点以外的其他结点有且仅有一个双亲结点。上层和下一层类型的联系是 1:n 联系(包括 1:1 联系)。
采用网络结构表示数据间联系的数据模型称为网状模型。在网状模型中,允许一个以上的结点无双亲,或者一个结点可以有多于一个的双亲。
网状模型是一个比层次模型更具有普遍性的数据结构,层次模型是网状模型的一个特例。网状模型可以直接地描述现实世界,因为去掉了层次模型的两个限制,允许两个结点之间有多种联系(称之为复合联系)。需要说明的是,网状模型不能表示记录之间的多对多联系,需要引入联结记录来表示多对多联系。
层次或网状模型,底层的数据结构均可用图来表示。二者的共同特点如下。
- 支持三级模式的体系结构;
- 用存取路径来表示数据之间的联系;
- 独立的数据定义语言;
- 导航的数据操纵语言。
2.关系数据库系统
关系模型 (Relation Model) 是目前最常用的数据模型之一。关系数据库系统采用关系模型作为数据的组织方式,在关系模型中用表格结构表达实体集以及实体集之间的联系,其最大特色是描述的一致性。关系模型是由若干个关系模式组成的集合。一个关系模式相当于一个记录型,对应于程序设计语言中类型定义的概念。关系是一个实例,也是一张表,对应于程序设计语言中变量的概念。变量的值随时间可能会发生变化,类似地,当关系被更新时,关系实例的内容也发生了变化。
由于关系模型比网状、层次模型更为简单灵活,因此,数据处理领域中,关系数据库的使用已相当普遍。
3.第三代数据库系统
层次、网状和关系数据库系统的设计目标源于商业事务处理,面对当前层出不穷的新型应用显得力不从心。从 20 世纪 80 年代开始,出现了许多新型应用,数据管理出现了许多新的数据模型,如面向对象模型、语义数据模型、XML 数据模型、半结构化数据模型等。数据模型的发展,需要数据库系统支持日益复杂的数据类型。其中最典型的是 No SQL(Not Only of SQL) 运动。
No SQL 一词最早出现于 1998 年,是 Carlo Strozzi 开发的一个轻量、开源、不提供 SQL 功能的关系数据库。2009 年,Last.fm 的 Johan Oskarsson 发起了一次关于分布式开源数据库的讨论,来自 Rackspace 的 Eric Evans 再次提出了 No SQL 的概念,这时的 No SQL 主要指非关系型、分布式、不提供 ACID 的数据库设计模式。2009 年在亚特兰大举行的讨论会是一个里程碑,其口号是 “select fun,profit from real_world where relational=false;"。因此,对 NoSQL 最普遍的解释是"非关联型的”,强调 Key-Value Stores 和文档数据库的优点,而不是单纯的反对 RDBMS。
随着互联网 Web2.0 网站的兴起,传统的关系数据库在处理 Web 2.0 网站,特别是超大规模和高并发的 SNS 类型的 Web2.0 纯动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。No SQL 数据库的产生就是为了面对大规模数据集合和多重数据种类带来的挑战,特别是大数据应用难题。
6.1.3 数据库管理系统
DBMS 实现了对共享数据有效地组织、管理和存取,因此 DBMS 应具有如下几个方面的功能及特征。
1.DBMS 功能
DBMS 功能主要包括数据定义、数据库操作、数据库运行管理、数据组织、存储和管理、数据库的建立和维护。
- 数据定义。 DBMS 提供数据定义语言 (Data Definition Language,DDL), 可以对数据库的结构进行描述,包括外模式、模式和内模式的定义;数据库的完整性定义;安全保密定义,如口令、级别和存取权限等。这些定义存储在数据字典中,是 DBMS 运行的基本依据。
- 数据库操作。 DBMS 向用户提供数据操纵语言 (Data Manipulation Language,DML), 实现对数据库中数据的基本操作,如检索、插入、修改和删除。
- 数据库运行管理。 数据库在运行期间,多用户环境下的并发控制、安全性检查和存取控制、完整性检查和执行、运行日志的组织管理、事务管理和自动恢复等都是 DBMS 的重要组成部分。这些功能可以保证数据库系统的正常运行。
- 数据组织、存储和管理。 DBMS 分类组织、存储和管理各种数据,包括数据字典、用户数据和存取路径等。要确定以何种文件结构和存取方式在存储级别上组织这些数据,以提高存取效率。实现数据间的联系、数据组织和存储的基本目标是提高存储空间的利用率。
- 数据库的建立和维护。 数据库的建立和维护,包括数据库的初始建立、数据的转换、数据库的转储和恢复、数据库的重组和重构、性能监测和分析等。
- 其他功能。 如 DBMS 与网络中其他软件系统的通信功能,一个 DBMS 与另一个 DBMS 或文件系统的数据转换功能等。
2. DBMS 的特点
通过 DBMS 来管理数据具有如下特点。
- 数据结构化且统一管理。数据库中的数据由 DBMS 统一管理。由于数据库系统采用数据模型表示数据结构,数据模型不仅描述数据本身的特点,还描述数据之间的联系。数据不再面向某个应用,而是面向整个企业内的所有应用。数据易维护、易扩展,数据冗余明显减少,真正实现了数据的共享。
- 有较高的数据独立性。数据的独立性是指数据与程序独立,将数据的定义从程序中分离出去,由 DBMS 负责数据的存储,应用程序关心的只是数据的逻辑结构,无须了解数据在磁盘上的存储形式,从而简化应用程序,大大减少应用程序编制的工作量。数据的独立性包括数据的物理独立性和数据的逻辑独立性。
- 数据控制功能。DBMS 提供了数据控制功能,以适应共享数据的环境。数据控制功能包括对数据库中数据的安全性、完整性、并发和恢复的控制。
- 数据库的安全性 (Security) 是指保护数据库以防止不合法的使用所造成的数据泄露、更改或破坏。这样,用户只能按规定对数据进行处理,例如,划分了不同的权限,有的用户只有读数据的权限,有的用户有修改数据的权限,用户只能在规定的权限范围内操纵数据库。
- 数据的完整性 (Integrality) 是指数据库正确性和相容性,是防止合法用户使用数据库时向数据库加入不符合语义的数据。保证数据库中数据是正确的,避免非法的更新。
- 并发控制 (concurrency control) 是指在多用户共享的系统中,许多用户可能同时对同一数据进行操作。DBMS 的并发控制子系统负责协调并发事务的执行,保证数据库的完整性不受破坏,避免用户得到不正确的数据。
- 故障恢复 (recovery from failure)。数据库中的常见故障是事务内部故障、系统故障、介质故障及计算机病毒等。故障恢复主要是指恢复数据库本身,即在故障导致数据库状态不一致时,将数据库恢复到某个正确状态或一致状态。恢复的原理非常简单,就是要建立冗余 (redundancy) 数据。换句话说,确定数据库是否可恢复的方法就是其包含的每一条信息是否都可以利用冗余的存储在别处的信息重构。
6.1.4 数据库三级模式
站在数据库管理系统的角度看,数据库系统一般采用三级模式结构,其体系结构如图 6-1 所示。事实上,一个可用的数据库系统必须能够高效地检索数据。这种高效性的需求促使数据库设计者使用复杂的数据结构来表示数据。由于大多数数据库系统用户并未受过计算机的专业训练,因此系统开发人员需要通过视图层、逻辑层和物理层三个层次上的抽象来对用户屏蔽系统的复杂性,简化用户与系统的交互。

- 视图层 (View Level) 是最高层次的抽象,描述整个数据库的某个部分的数据。因为数据库系统的很多用户并不关心数据库中的所有信息,而只关心所需要的那部分数据。可以通过构建视图层来实现用户的数据需求,这样做不仅使用户与系统交互简化,而且还可以保证数据的保密性和安全性。
- 逻辑层 (Logical Level) 是比物理层更高一层的抽象,描述数据库中存储的数据以及这些数据间存在的关系。逻辑层通过相对简单的结构描述了整个数据库。尽管逻辑层简单结构的实现涉及了复杂的物理层结构,但逻辑层的用户不必知道这些复杂性。因为,逻辑层抽象是数据库管理员的职责,管理员确定数据库应保存哪些信息。
- 物理层 (Physical Level) 是最低层次的抽象,描述数据在存储器中是如何存储的。物理层详细地描述复杂的底层结构。
实际上,数据库的产品很多,它们支持不同的数据模型,使用不同的数据库语言,建立在不同的操作系统上,而且数据的存储结构也各不相同,但基本上都支持三级模式。
数据库系统采用三级模式结构,这是数据库管理系统内部的系统结构。数据库有"型"和"值"的概念,“型"是指对某一数据的结构和属性的说明,“值"是型的一个具体赋值。
从数据库管理系统的角度,数据库也分为三级模式,分别是外模式、概念模式和内模式。
概念模式也称模式,是数据库中全部数据的逻辑结构和特征的描述,它由若干个概念记录类型组成,只涉及"型"的描述,不涉及具体的值。概念模式的一个具体值称为模式的一个实例,同一个模式可以有很多实例。概念模式反映的是数据库的结构及其联系,所以是相对稳定的;而实例反映的是数据库某一时刻的状态,是相对变动的。
需要说明的是,概念模式不仅要描述概念记录类型,还要描述记录间的联系、操作、数据的完整性和安全性等要求。但是,概念模式不涉及存储结构、访问技术等细节。只有这样,概念模式才算做到了"物理数据独立性”。
外模式也称用户模式或子模式,是用户与数据库系统的接口,是用户需要使用的部分数据的描述。它由若干个外部记录类型组成。用户使用数据操纵语言对数据库进行操作,实际上是对外模式的外部记录进行操作。
内模式也称存储模式,是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。定义所有的内部记录类型、索引和文件的组织方式,以及数据控制方面的细节。
总之,数据按外模式的描述提供给用户,按内模式的描述存储在磁盘上,而概念模式提供了连接这两极模式的相对稳定的中间观点,并使得两级的任意一级的改变都不受另一级的牵制。
6.2 关系数据库
关系数据库是目前应用非常广泛的数据库之一,有一套完整的理论支持。关系模型是关系数据库的基础,由关系数据结构、关系操作集合和关系完整性规则 3 部分组成。本节介绍关系模型的基本概念、关系代数、关系演算和关系数据库设计理论方面的内容。
6.2.1 关系数据库基本概念
关系数据库系统是支持关系数据模型的数据库系统。关系数据库应用数学方法来处理数据库中的数据。最早提出将这类方法用于数据处理的是 1962 年 CODASYL 发表的"信息代数"一文,之后 1968 年 David Child 在 7090 机上实现了集合论数据结构,但系统而严格地提出关系模型的是美国 IBM 公司的 E.F.Codd。
1970 年 E.F.Codd 在美国计算机学会会刊 Communication of the ACM 上发表的题为 A Relational Model of Data for Shared Data Banks 的论文,开创了数据库系统的新纪元。此后,他连续发表了多篇论文,奠定了关系数据库的理论基础。
几十年来,关系数据库系统的研究取得了辉煌的成就。关系方法从实验室走向了社会,涌现出许多性能良好的商业化关系数据库管理系统 (RDBMS), 如著名的 IBM DB2、Oracle、Ingres、SYBASE、Informix 等。数据库的应用领域迅速扩大。
1.关系的基本术语
- 属性 (Attribute): 在现实世界中,要描述一个事物常常取若干特征来表示。这些特征称为属性。例如学生通过学号、姓名、性别、系别、年龄、籍贯等属性来描述。
- 域 (Domain): 每个属性的取值范围对应一个值的集合,称为该属性的域。例如,学号的域是 6 位整型数;姓名的域是 10 位字符;性别的域为{男,女}等。一般在关系数据模型中,对域还加了一个限制,即所有的域都应是原子数据 (Atomic Data)。例如,整数、字符串是原子数据,而集合、记录、数组是非原子数据。关系数据模型的这种限制称为第一范式 (First Normal Form,1NF) 条件。但也有些关系数据模型突破了 1NF 的限制。
- 目或度 (Degree): 目或度指的是一个关系中属性的个数。
- 候选码 (Candidate Key): 若关系中的某一属性或属性组的值能唯一的标识一个元组,则称该属性或属性组为候选码。
- 主码 (Primary Key): 或称主键,若一个关系有多个候选码,则选定其中一个作为主码。
- 主属性 (Prime Attribute): 包含在任何候选码中的属性称为主属性。不包含在任何候选码中的属性称为非主属性 (Non-Prime Attribute)。
- 外码 (Foreign Key): 如果关系模式 R 中的属性或属性组不是该关系的码,但它是其他关系的码,那么该属性集对关系模式 R 而言是外码。
例如,客户与贷款之间的借贷联系 c-1(c-id,loan-no), 属性 c-id 是客户关系中的码,所以 c-id 是外码;属性 loan-no 是贷款关系中的码,所以 loan-no 也是外码。
- 全码 (All-key): 关系模型的所有属性组是这个关系模式的候选码,称为全码。
例如,关系模式 R(T,C,S), 属性 T 表示教师,属性 C 表示课程,属性 S 表示学生。假设一个教师可以讲授多门课程,某门课程可以由多个教师讲授,学生可以听不同教师讲授的不同课程,那么,要想区分关系中的每一个元组,这个关系模式 R 的码应为全属性 T、C 和 S, 即 ALL-KEY。
- 笛卡尔积:
【定义 6.1】 设 $D_1,D_2,D_3,\ldots,D_n$ 为任意集合,定义 $D_1,D_2,D_3,\ldots,D_n$ 的笛卡尔积为:
$D_1 \times D_2 \times D_3 \times \ldots \times D_n = {(d_1,d_2,d_3,\ldots,d_n) | d_i \in D_i, i=1,2,3,\ldots,n}$
其中,集合中的每一个元素 $(d_1,d_2,d_3,\ldots,d_n)$ 叫作一个 n 元组 (n-tuple, 即 n 个属性的元组),元素中的每一个值 $d_i$ 叫作元组一个分量。若 $D_i (i=1,2,3,\ldots,n)$ 为有限集,其基数 (Cardinal Number, 元组的个数)为 $m_i (i=1,2,3,\ldots,n)$, 则 $D_1 \times D_2 \times D_3 \times \ldots \times D_n$ 的基数 M
2.关系数据库模式
在数据库中要区分型和值。关系数据库中的型也称为关系数据库模式,是关系数据库结构的描述。它包括若干域的定义以及在这些域上定义的若干关系模式。关系数据库的值是这些关系模式在某一时刻对应的关系的集合,通常称之为关系数据库。
【定义 6.2】 关系的描述称为关系模式 (Relation Schema)。可以形式化地表示为:
$R(U,D,dom,F)$
其中,R 表示关系名;U 是组成该关系的属性名集合;D 是属性的域;dom 是属性向域的映像集合;F 为属性间数据的依赖关系集合。
通常将关系模式简记为:
$R(U)$ 或 $R(A_1,A_2,A_3,\ldots,A_n)$
其中,R 为关系名,$A_1,A_2,A_3,\ldots,A_n$ 为属性名或域名,属性向域的映像常常直接说明属性的类型、长度。通常在关系模式主属性上加下画线表示该属性为主码属性。
例如:学生关系 S 有学号 Sno、学生姓名 Sname、系名 SD、年龄 SA 属性;课程关系 C 有课程号 Cno、课程名 Cname、先修课程号 PCno 属性;学生选课关系 SC 有学号 Sno、课程号 Cno、成绩 Grade 属性。定义关系模式及主码如下(本题未考虑 F 属性间数据的依赖,该问题在后续内容讨论)。
- 学生关系模式 S(Sno,Sname,SD,SA)。
- 课程关系模式 C(Cno,Cname,PCno),Dom(PCno)=Cno。这里,PCno 是先行课程号,来自 Cno 域,但由于 PCno 属性名不等于 Cno 值域名,所以要用 Dom 来定义。但是,不能将 PCno 直接改为 Cno, 因为在关系模型中,各列属性必须取相异的名字。
- 学生选课关系模式 SC(Sno,Cno,Grade)。SC 关系中的 Sno、Cno 又分别为外码。因为它们分别是 S、C 关系中的主码。
3.关系的完整性约束
完整性规则提供了一种手段来保证当授权用户对数据库做修改时不会破坏数据的一致性。因此,完整性规则防止的是对数据的意外破坏。关系模型的完整性规则是对关系的某种约束条件。例如,若某企业实验室管理员的基本薪资小于 2000 元,则可用完整性规则来进行约束。
关系的完整性约束共分为 3 类:实体完整性、参照完整性(也称引用完整性)和用户定义完整性。
- 实体完整性 (Entity Integrity)。实体完整性规则要求每个数据表都必须有主键,而作为主键的所有字段,其属性必须是唯一且非空值。
- 参照完整性 (Referential Integrity)。现实世界中的实体之间往往存在某种联系,在关系模型中实体及实体间的联系是用关系来描述的,这样自然就存在着关系与关系间的引用。参照完整性规定:若 F 是基本关系 R 的外码,它与基本关系 S 的主码 Ks 相对应(基本关系 R 和 S 不一定是不同的关系),则对于 R 中每个元组在 F 上的值或者取空值 (F 的每个属性值均为空值),或者等于 S 中某个元组的主码值。
例如,某企业员工 Emp 关系模式和部门 Dept 关系模式表示如下:
Emp (员工号,姓名,性别,参加工作时间,部门号)
Dept (部门号,名称,电话,负责人)
Emp 和 Dept 关系存在着属性的引用,即员工关系中的"部门号"值必须是确实存在的部门的部门号。按照关系的完整性规则,员工关系中的"部门号"属性取值要参照部门关系的"部门号"属性取值。如果新入职的员工还未分配具体的部门,那么部门号取空值。
注意:本书若在关系模式主属性上加实下画线,通常表示该属性为主码属性;如果在关系模式属性上加虚下画线,通常表示该属性为外码属性。
- 用户定义完整性 (User Defined Integrity)。就是针对某一具体的关系数据库的约束条件,反映某一具体应用所涉及的数据必须满足的语义要求,由应用的环境决定。例如,银行的用户账户规定必须大于等于 100000,小于 999999。
6.2.2 关系运算
关系操作的特点是操作对象和操作结果都是集合。
关系代数运算符有 4 类:集合运算符、专门的关系运算符、算术比较符和逻辑运算符。根据运算符的不同,关系代数运算可分为传统的集合运算和专门的关系运算。传统的集合运算是从关系的水平方向进行的,包括并、交、差及广义笛卡儿积。专门的关系运算既可以从关系的水平方向进行运算,又可以向关系的垂直方向运算,包括选择、投影、连接以及除法,如表 6-1 所示。

5 种基本的关系代数运算包括并、差、笛卡尔积、投影和选择,其他运算可以通过基本的关系运算导出。
1.并 (Union)
关系 R 与 S 具有相同的关系模式,即 R 与 S 的元数相同(结构相同)。关系 R 与 S 的并由属于 R 或属于 S 的元组构成的集合组成,记作 $R \cup S$, 其形式定义如下,式中 t 为元组变量。
2.差 (Difference)
关系 R 与 S 具有相同的关系模式,关系 R 与 S 的差是由属于 R 但不属于 S 的元组构成的集合,记作 $R-S$, 其形式定义如下:
3.广义笛卡尔积 (Extended Cartesian Product)
两个元数分别为 n 目和 m 目的关系 R 和 S 的广义笛卡尔积是一个 (n+m) 列的元组的集合。元组的前 n 列是关系 R 的一个元组,后 m 列是关系 S 的一个元组,记作 $R \times S$, 其形式定义如下:
如果 R 和 S 中有相同的属性名,可在属性名前加关系名作为限定,以示区别。若 R 有 $K_1$ 个元组,S 有 $K_2$ 个元组,则 R 和 S 的广义笛卡尔积有 $K_1 \times K_2$ 个元组。
注意:本书中的 $<t^{(n)},t^{(m)}>$ 意为元组 $t^{(n)}$ 和 $t^{(m)}$ 拼接成的一个元组。
4.投影 (Projection)
投影运算是从关系的垂直方向进行运算,在关系 R 中选择出若干属性列 A 组成新的关系,记作 $\pi_A(R)$, 其形式定义如下:
5.选择 (Selection)
选择运算是从关系的水平方向进行运算,是从关系 R 中选择满足给定条件的诸元组,记作 $\sigma_F(R)$, 其形式定义如下:
$\sigma_F(R) = { t | t \in R \wedge F(t) = \text{True} }$
其中,F 中的运算对象是属性名(或列的序号)或常数,由运算符、算术比较符(<、$\leq$、>、$\geq$、$\neq$)和逻辑运算符($\wedge$、$\vee$、$\rightarrow$)构成。例如,$\sigma_{1 \geq 6}(R)$ 表示选取 R 关系中第 1 个属性值大于等于第 6 个属性值的元组;$\sigma_{1>6}(R)$ 表示选取 R 关系中第 1 个属性值大于等于 6 的元组。
扩展的关系运算可以从基本的关系运算中导出,主要包括:选择、投影、连接、除法、广义笛卡尔积、外连接。
6.交 (Intersection)
关系 R 与 S 具有相同的关系模式,关系 R 与 S 的交是由属于 R 同时又属于 S 的元组构成的集合,关系 R 与 S 的交可记为 $R \cap S$, 其形式定义如下:
显然,$R \cap S = R-(R-S)$, 或者
7.连接 (Join)
连接分为 θ 连接、等值连接及自然连接 3 种。连接运算是从两个关系 R 和 S 的笛卡尔积中选取满足条件的元组。因此,可以认为笛卡尔积是无条件连接,其他的连接操作是有条件连接。下面分述如下。
- θ 连接
θ 连接是从 R 与 S 的笛卡尔积中选取属性满足一定条件的元组。其形式定义如下:
$R \underset{X \theta Y}{\bowtie} S = { t^{(n+m)} | t^{(n)} \in R \wedge t^{(m)} \in S \wedge t^{(n)}[X] \theta t^{(m)}[Y] }$
其中:$X \theta Y$ 为连接的条件,θ 是比较运算符,X 和 Y 分别为 R 和 S 上度数相等,且可比的属性组。$t^{(n)}[X]$ 表示 R 中 $t^{(n)}$ 元组的相应于属性 X 的一个分量。$t^{(m)}[Y]$ 表示 S 中 $t^{(m)}$ 元组的相应于属性 Y 的一个分量。需要说明的是:
(1) θ 连接也可以表示为:
$R \underset{i \theta j}{\bowtie} S = { t^{(n+m)} | t^{(n)} \in R \wedge t^{(m)} \in S \wedge t^{(n)}[i] \theta t^{(m)}[j] }$
其中:$i=1,2,3,\ldots,n, j=1,2,3,\ldots,m, t^{(n)}[i] \theta t^{(m)}[j]$ 的含义为从两个关系 R 和 S 中选取 R 的第 i 列和 S 的第 j 列之间满足 θ 运算的元组进行连接。
(2) θ 连接可以由基本的关系运算笛卡尔积和选取运算导出。因此 θ 连接可表示为:
$R \underset{X \theta Y}{\bowtie} S = \sigma_{X \theta Y}(R \times S)$ 或 $R \underset{i \theta j}{\bowtie} S = \sigma_{i \theta j}(R \times S)$
- 等值连接 (Equijoin)
当 θ 为”=“时,称之为等值连接,记为 $R \underset{X=Y}{\bowtie} S$。其形式定义如下:
$R \underset{X=Y}{\bowtie} S = { t^{(n+m)} | t^{(n)} \in R \wedge t^{(m)} \in S \wedge t^{(n)}[X] = t^{(m)}[Y] }$
- 自然连接 (Natural Join) 是一种特殊的等值连接,它要求两个关系中进行比较的分量必须是相同的属性组,并且在结果集中将重复属性列去掉。
若 $t^{(n)}$ 表示 R 关系的元组变量,$t^{(m)}$ 表示 S 关系的元组变量;R 和 S 具有相同的属性组 B, 且 $B=(B_1,B_2,\ldots,B_k)$; 并假定 R 关系的属性为 $A_1,A_2,\ldots,A_{n-k},B_1,B_2,\ldots,B_k$, S 关系的属性为 $B_1,B_2,\ldots,B_k,B_{k+1},B_{k+2},\ldots,B_m$; 为 S 的元组变量 $t^{(m)}$ 去掉重复属性 B 所组成的新的元组变量为 $t^{(m-1)}$。
自然连接可以记为 $R \bowtie S$, 其形式定义如下:
$R \bowtie S = { t^{(n+m-k)} | t^{(n)} \in R \wedge t^{(m)} \in S \wedge R.B_1 = S.B_1 \wedge R.B_2 = S.B_2 \wedge \ldots \wedge R.B_k = S.B_k }$
自然连接可以由基本的关系运算笛卡尔积和选取运算导出,因此自然连接可表示为:
$R \bowtie S = \pi_{A_1,A_2,\ldots,A_{n-k},R.B_1,R.B_2,\ldots,R.B_k,B_{k+1},B_{k+2},\ldots,B_m}(\sigma_{R.B_1=S.B_1 \wedge R.B_2=S.B_2 \wedge \ldots \wedge R.B_k=S.B_k}(R \times S))$
特别需要说明的是:一般连接是从关系的水平方向运算,而自然连接不仅要从关系的水平方向,而且也要从关系的垂直方向运算。因为自然连接要去掉重复属性,如果没有重复属性,那么自然连接就转化为笛卡儿积。
8.除 (Division)
除运算同时从关系的水平方向和垂直方向进行运算。给定关系 $R(X,Y)$ 和 $S(Y,Z)$, X、Y、Z 为属性组。$R \div S$ 应当满足元组在 X 上的分量值 x 的象集 $Y_x$ 包含关系 S 在属性组 Y 上投影的集合。其形式定义如下:
$R \div S = { t_r[X] | t_r \in R \wedge \pi_Y(S) \subseteq Y_x }$
其中:$Y_x$ 为 x 在 R 中的象集,$x = t_r[X]$。且 $R \div S$ 的结果集的属性组为 X。
9.广义投影 (Generalized Projection)
广义投影运算允许在投影列表中使用算术运算,实现了对投影运算的扩充。
若有关系 R, 条件 $F_1,F_2,\ldots,F_n$ 中的每一个都是涉及 R 中常量和属性的算术表达式,那么广义投影运算的形式定义为:$\pi_{F_1,F_2,\ldots,F_n}(R)$。
10.外连接 (Outer Join)
外连接运算是连接运算的扩展,可以处理缺失的信息。外连接运算有三种:左外连接、右外连接和全外连接。
- 左外连接 (Left Outer Join):取出左侧关系中所有与右侧关系中任一元组都不匹配的元组,用空值 null 充填所有来自右侧关系的属性,构成新的元组,将其加入自然连接的结果中。
- 右外连接 (Right Outer Join):取出右侧关系中所有与左侧关系中任一元组都不匹配的元组,用空值 null 填充所有来自左侧关系的属性,构成新的元组,将其加入自然连接的结果中。
- 全外连接 (Full Outer Join):完成左外连接和右外连接的操作。即填充左侧关系中所有与右侧关系中任一元组都不匹配的元组,又填充右侧关系中所有与左侧关系中任一元组都不匹配的元组,将产生的新元组加入自然连接的结果中。
11.聚集函数
聚集运算是关系代数运算中的一个非常重要的扩展。聚集函数输入一个值的集合,返回单一值作为结果。例如,集合 {2,4,6,8,10,15}。将聚集函数 sum 用于该集合时返回和 45;将聚集函数 avg 用于该集合时返回平均值 7.5;将聚集函数 count 用于该集合时返回集合中元数的个数 6;将聚集函数 min 用于该集合时返回最小值 2;将聚集函数 max 用于该集合时返回最大值 15。
需要说明的是,使用聚集函数的集合中,一个值可以出现多次,值出现的顺序是无关紧要的,这样的集合称之为多重集。集合是多重集的一个特例,其中每个值都只出现一次。
但是,有时在计算聚集函数前必须去掉重复值,此时可以将 distinct 用连接符附加在函数名后,如 count-distinct。
6.2.3 关系数据库设计基本理论
关系数据理论是指导数据库设计的基础,关系数据库设计是数据库语义学的问题。要保证构造的关系既能准确地反应现实世界,又有利于应用和具体的操作。关系数据库设计的目标是生成一组合适的、性能良好的关系模式,以减少系统中信息存储的冗余度,但又可以方便地获取信息。
1.函数依赖
数据依赖是通过一个关系中属性间值的相等与否体现出来的数据间的相互关系,是现实世界属性间联系和约束的抽象,是数据内在的性质,是语义的体现。函数依赖则是一种最重要、最基本的数据依赖。
【定义 6.3】 设 R(U) 是属性集 U 上的关系模式,X→Y 是 U 的子集。若对 R(U) 的任何一个可能的关系 r,r 中不可能存在两个元组在 X 上的属性值相等,而在 Y 上的属性值不等,则称 X 函数决定 Y 或 Y 函数依赖于 X, 记作:$X \rightarrow Y$。
如果 $X \rightarrow Y$, 但 $Y \not\subseteq X$, 则称 $X \rightarrow Y$ 是非平凡的函数依赖。一般情况下总是讨论非平凡的函数依赖。
如果 $X \rightarrow Y$, 但 $Y \subseteq X$, 则称 $X \rightarrow Y$ 是平凡的函数依赖。
注意:函数依赖 $X \rightarrow Y$ 的定义要求关系模式 R 的任何可能的 r 都满足上述条件。因此不能仅考察关系模式 R 在某一时刻的关系 r, 就断定某函数依赖成立。
例如,关系模式 Student(Sno,Sname,SD,Sage,Sex) 可能在某一时刻,Student 的关系 r 中每个学生的年龄都不同,也就是说没有两个元组在 Sage 属性上取值相同,而在 Sno 属性上取值不同,但我们决不可据此就断定 Sage →Sno。很有可能在某一时刻,Student 的关系 r 中有两个元组在 Sage 属性上取值相同,而在 Sno 属性上取值不同。
函数依赖是语义范畴的概念,我们只能根据语义来确定函数依赖。例如,在没有同名的情况下,Sname →Sage, 而在允许同名的情况下,这个函数依赖就不成立了。
【定义 6.4】 在 R(U) 中,如果 $X \rightarrow Y$, 并且对于 X 的任何一个真子集 $X’$, 都有 $X’$ 不能决定 Y, 则称 Y 对 X 完全函数依赖,记作:$X \overset{f}{\rightarrow} Y$。如果 $X \rightarrow Y$, 但 Y 不完全函数依赖于 X, 则称 Y 对 X 部分函数依赖,记作:$X \overset{p}{\rightarrow} Y$。部分函数依赖也称作局部函数依赖。
例如:给定一个学生选课关系 SC(Sno,Cno,G), 我们可以得到 F={(Sno,Cno)→G}, 对 (Sno,Cno) 中的任何一个真子集 Sno 或 Cno 都不能决定 G, 所以,G 完全依赖于 Sno,Cno。
【定义 6.5】 在 R(U,F) 中,如果 $X \rightarrow Y, Y \not\subseteq X, Y \nrightarrow X, Y \rightarrow Z$, 则称 Z 对 X 传递依赖。
2.多值依赖
【定义 6.6】 若关系模式 R(U) 中,X、Y、Z 是 U 的子集,并且 $Z=U-X-Y$ 当且仅当对 R(U) 的任何一个关系 r, 给定一对 (x, z) 值,有一组 Y 的值,这组值只由 x 值决定而与 z 值无关,则称"Y 多值依赖于 X"或"X 多值决定 Y"成立。记为:$X \rightarrow \rightarrow Y$。
多值依赖具有以下 6 条性质:
- 多值依赖具有对称性。即若 $X \rightarrow \rightarrow Y$, 则 $X \rightarrow \rightarrow Z$, 其中 $Z=U-X-Y$
- 多值依赖具有传递性。即若 $X \rightarrow \rightarrow Y, Y \rightarrow \rightarrow Z$, 则 $X \rightarrow \rightarrow Z-Y$。
- 函数依赖可以看成是多值依赖的特殊情况。
- 若 $X \rightarrow \rightarrow Y, X \rightarrow \rightarrow Z$, 则 $X \rightarrow \rightarrow YZ$。
- 若 $X \rightarrow \rightarrow Y, X \rightarrow \rightarrow Z$, 则 $X \rightarrow \rightarrow Y \cap Z$。
- 若 $X \rightarrow \rightarrow Y, X \rightarrow \rightarrow Z$, 则 $X \rightarrow \rightarrow Z-Y$。
3.规范化
关系数据库设计的方法之一就是设计满足适当范式的模式,通常可以通过判断分解后的模式达到几范式来评价模式规范化的程度。范式有:1NF、2NF、3NF、BCNF、4NF 和 5NF, 其中 1NF 级别最低。这几种范式之间 $1NF \supseteq 2NF \supseteq 3NF \supseteq BCNF \supseteq 4NF \supseteq 5NF$ 成立。
通过分解,可以将一个低一级范式的关系模式转换成若干个高一级范式的关系模式,这种过程叫作规范化。下面将给出 1NF 到 4NF 的定义。
- 1NF
【定义 6.7】 若关系模式 R 的每一个分量都是不可再分的数据项,则关系模式 R 属于第一范式。记为 $R \in 1NF$。
例如,供应者和它所提供的零件信息,关系模式 FIRST 和函数依赖集 F 如下:
FIRST(Sno,Sname,Status,City,Pno,Qty)
F={Sno → Sname,Sno → Status,Status → City,(Sno,Pno)→ Qty}
对具体的关系 FIRST 如表 6-2 所示。从表 6-2 中可以看出,每一个分量都是不可再分的数据项,所以是 1NF 的。但是,1NF 存在 4 个问题。

- 冗余度大。例如每个供应者的 Sno、Sname、Status、City 要与其供应的零件的种类一样多。
- 引起修改操作的不一致性。例如供应者 S1 从"天津"搬到"上海”,若不注意,会使一些数据被修改,另一些数据未被修改,导致数据修改的不一致性。
- 插入异常。关系模式 FRIST 的主码为 Sno、Pno, 按照关系模式实体完整性规定主码不能取空值或部分取空值。这样,当某个供应者的某些信息未提供时(如 Pno), 则不能进行插入操作,这就是所谓的插入异常。
- 删除异常。若供应商 S4 的 P2 零件销售完了,并且以后不再销售 P2 零件,那么应删除该元组。这样,在基本关系 FIRST 找不到 S4, 可 S4 又是客观存在的。
正因为上述 4 个原因,所以要对模式进行分解,并引入了 2NF。
- 2NF
【定义 6.8】 若关系模式 R∈1NF, 且每一个非主属性完全依赖于码,则关系模式 R∈2NF。换句话说,当 1NF 消除了非主属性对码的部分函数依赖,则称为 2NF。
例如:FIRST 关系中的码是 Sno、Pno, 而 Sno→Status, 因此非主属性 Status 部分函数依赖于码,故非 2NF 的。
若此时,将 FIRST 关系分解为:
FIRST1(Sno,Sname,Status,City) 2NF
FIRST2(Sno,Pno,Qty) 2NF
因为分解后的关系模式 FIRST1 的码为 Sno, 非主属性 Sname、Status、City 完全依赖于码 Sno, 所以属于 2NF;关系模式 FIRST2 的码为 Sno、Pno, 非主属性 Qty 完全依赖于码,所以也属于 2NF。
- 3NF
【定义 6.9】 若关系模式 R(U,F) 中不存在这样的码 X, 属性组 Y 及非主属性 Z(Z⊈Y) 使得 $X \rightarrow Y, (Y \nrightarrow X) Y \rightarrow Z$ 成立,则关系模式 $R \in 3NF$。
即当 2NF 消除了非主属性对码的传递函数依赖,则称为 3NF。
例如:FIRST1∉3NF, 因为在分解后的关系模式 FIRST1 中有 Sno→Status,Status→City, 存在着非主属性 City 传递依赖于码 Sno。若此时将 FIRST1 继续分解为:
FIRST11(Sno,Sname,Status) 3NF
FIRST12(Status,City) 3NF
通过上述分解,数据库模式 FIRST 转换为 FIRST11(Sno,Sname,Status),FIRST12(Status,City),FIRST2(Sno,Pno,Qty) 3 个子模式。由于这 3 个子模式都达到了 3NF, 因此称分解后的数据库模式达到了 3NF。
可以证明,3NF 的模式必是 2NF 的模式。产生冗余和异常的两个重要原因是部分依赖和传递依赖。因为 3NF 模式中不存在非主属性对码的部分函数依赖和传递函数依赖,所以具有较好的性能。对于非 3NF 的 1NF、2NF 来说,其性能弱,一般不宜作为数据库模式,通常要将它们变换成为 3NF 或更高级别的范式,这种变换过程称为"关系模式的规范化处理"。
- BCNF(Boyce Codd Normal Form, 巴克斯范式)
【定义 6.10】 关系模式 R∈1NF, 若 X→Y 且 Y⊈X 时,X 必含有码,则关系模式 R∈BCNF。也就是说,当 3NF 消除了主属性对码的部分函数依赖和传递函数依赖,则称为 BCNF。
结论:一个满足 BCNF 的关系模式,应有如下性质:
- 所有非主属性对每一个码都是完全函数依赖;
- 所有非主属性对每一个不包含它的码,也是完全函数依赖;
- 没有任何属性完全函数依赖于非码的任何一组属性。
例如,设 R(Pno,Pname,Mname) 的属性分别表示零件号、零件名和厂商名,如果约定,每种零件号只有一个零件名,但不同的零件号可以有相同的零件名;每种零件可以有多个厂商生产,但每家厂商生产的零件应有不同的零件名。这样我们可以得到如下一组函数依赖:
Pno → Pname,(Pname,Mname)→ Pno
由于该关系模式 R 中的候选码为 (Pname,Mname) 或 (Pno,Mname), 因而关系模式 R 的属性都是主属性,不存在非主属性对码的传递依赖,所以 R 是 3NF 的。但是,主属性 Pname 传递依赖于码 (Pname,Mname), 因此 R 不是 BCNF 的。当一种零件由多个生产厂家生产时,零件名与零件号间的联系将多次重复,带来冗余和操作异常现象。若将 R 分解成:
R1(Pno,Pname) 和 R2(Pno,Mname)
就可以解决上述问题,并且分解后的关系模式 R1、R2 都属于 BCNF。
- 4NF
【定义 6.11】 关系模式 R∈1NF, 若对于 R 的每个非平凡多值依赖 $X \rightarrow \rightarrow Y$ 且 Y≠X 时,X 必含有码,则关系模式 $R(U,F) \in 4NF$。
4NF 是限制关系模式的属性间不允许有非平凡且非函数依赖的多值依赖。
注意:如果只考虑函数依赖,关系模式最高的规范化程度是 BCNF;如果考虑多值依赖,关系模式最高的规范化程度是 4NF。
6.3 数据库设计
数据库设计的任务是针对一个给定的应用环境,在给定的硬件环境和操作系统及数据库管理系统等软件环境下,创建一个性能良好的数据库模式,建立数据库及其应用系统,使之能够有效地存储和管理数据,满足各类用户的需求。
数据库设计 (Database Design) 属于系统设计的范畴。通常把使用数据库的系统统称为数据库应用系统,把对数据库应用系统的设计简称为数据库设计。目前主流的数据库系统多数为关系数据库系统,所以本节的论述基本是关系数据库的设计。
6.3.1 数据库设计的基本步骤
多年来,人们提出了多种数据库设计方法,多种设计准则和规范。但考虑数据库和应用系统开发全过程,一般将数据库设计分为如下 6 个阶段。
- 用户需求分析。数据库设计人员采用一定的辅助工具对应用对象的功能、性能、限制等要求进行科学的分析。
- 概念结构设计。概念结构设计是对信息分析和定义,如视图模型化、视图分析和汇总。对应用对象精确地抽象、概括而形成独立于计算机系统的企业信息模型。描述概念模型的较理想的工具是 E-R 图。
- 逻辑结构设计。将抽象的概念模型转化为与选用的 DBMS 产品所支持的数据模型相符合的逻辑模型,它是物理结构设计的基础。包括模式初始设计、子模式设计、应用程序设计、模式评价以及模式求精。
- 物理结构设计。是逻辑模型在计算机中的具体实现方案。
- 数据库实施阶段。数据库设计人员根据逻辑设计和物理设计阶段的结果建立数据库,编制与调试应用程序,组织数据入库,并进行试运行。
- 数据库运行和维护阶段。数据库应用系统经过试运行即可投入运行,但该阶段需要不断地对系统进行评价、调整与修改。
6.3.2 数据需求分析
数据需求分析是在项目确定之后,用户和设计人员对数据库应用系统所要涉及的内容(数据)和功能(行为)的整理和描述,是以用户的角度来认识系统。这一过程是后续开发的基础,因为逻辑设计、物理设计以及应用程序的设计都会以此为依据。
需求分析阶段的任务:综合各个用户的应用需求,对现实世界要处理的对象(组织、部门和企业等)进行详细调查,在了解现行系统的概况,确定新系统功能的过程中,收集支持系统目标的基础数据及处理方法。
参与需求分析的主要人员是分析人员和用户,由于数据库应用系统是面向企业和部门的具体业务,分析人员一般并不了解,而同样用户也不会具有系统分析的能力,这就需要双方进行有效的沟通,使得设计人员对用户的各项业务了解和熟悉,进行分析和加工,将用户眼中的业务转换成为设计人员所需要的信息组织。
分析和表达用户需求的方法主要包括自顶向下和自底向上两类方法。自顶向下的结构化分析 (Structured Analysis,SA) 方法从最上层的系统组织机构入手,采用逐层分解的方式分析系统,并把每一层用数据流图和数据字典描述。需求分析的重点是调查组织机构情况、调查各部门的业务活动情况、协助用户明确对新系统的各种要求、确定新系统的边界,以此获得用户对系统的如下要求。
- 信息要求。用户需要在系统中保存哪些信息,由这些保存的信息要得到什么样的信息,这些信息以及信息间应当满足的完整性要求。
- 处理要求。用户在系统中要实现什么样的操作功能,对保存信息的处理过程和方式,各种操作处理的频度、响应时间要求、处理方式等以及处理过程中的安全性要求和完整性要求。
- 系统要求。包括安全性要求、使用方式要求和可扩充性要求。安全性要求:系统有几种用户使用,每一种用户的使用权限如何。使用方式要求:用户的使用环境是什么,平均有多少用户同时使用,最高峰时有多少用户同时使用,有无查询相应的时间要求等。可扩充性要求:对未来功能、性能和应用访问的可扩充性的要求。
6.3.3 概念结构设计
概念结构设计的目标是产生反映系统信息需求的数据库概念结构,即概念模式。概念结构是独立于支持数据库的 DBMS 和使用的硬件环境的。此时,设计人员从用户的角度看待数据以及数据处理的要求和约束,产生一个反映用户观点的概念模式,然后再把概念模式转换为逻辑模式。
概念结构设计最著名最常用的方法是 P.P.S Chen 于 1976 年提出的实体-联系方法 (Entity-Relationship Approach), 简称 E-R 方法。它采用 E-R 模型将现实世界的信息结构统一由实体、属性,以及实体之间的联系来描述。使用 E-R 方法,对现实事物加以抽象认识,以 E-R 图的形式描述出来。对现实事物抽象认识的 3 种方法分别是分类、聚集和概括。分类 (Classification): 对现实世界的事物,按照其具有的共同特征和行为,定义一种类型。聚集 (Aggregation): 定义某一类型所具有的属性。概括 (Generalization): 由一种已知类型定义新的类型。通常把已知类型称为超类 (Superclass), 新定义的类型称为子类 (Subclass)。子类是超类的一个子集,即 “is subset of”, 例如,研究生是学生的一个子集。
E-R 图的设计要依照上述的抽象机制,对需求分析阶段所得到的数据进行分类、聚集和概括,确定实体、属性和联系。概念结构设计工作步骤包括:选择局部应用、逐一设计分 E-R 图和 E-R 图合并。
1.选择局部应用
需求分析阶段会得到大量的数据,这些数据分散杂乱,许多数据应用于不同的处理,数据与数据之间的关联关系也较为复杂,要最终确定实体、属性和联系,就必须根据数据流图这一线索,理清数据。
数据流图是对业务处理过程从高层到底层的一级级抽象,高层抽象流图一般反映系统的概貌,对数据的引用较为笼统,而底层又可能过于细致,不能体现数据的关联关系,因此要选择适当层次的数据流图,让这一层的每一部分对应一个局部应用,实现某一项功能。从这一层入手,就能很好地设计分 E-R 图。
2.逐一设计分 E-R 图
划分好各个局部应用之后,就要对每一个局部应用逐一设计分 E-R 图,又称为局部 E-R 图。
对于每一局部应用,其所用到的数据都应该收集在数据字典中了,依照该局部应用的数据流图,从数据字典中提取出数据,使用抽象机制,确定局部应用中的实体、实体的属性、实体标识符及实体间的联系和其类型。
事实上,在形成数据字典的过程中,数据结构、数据流和数据存储都是根据现实事物来确定的,因此都已经基本上对应了实体及其属性,以此为基础,加以适当调整,增加联系及其类型,就可以设计分 E-R 图。
3. E-R 图合并
根据局部应用设计好各局部 E-R 图之后,就可以对各分 E-R 图进行合并。合并的目的在于在合并过程中解决分 E-R 图中相互间存在的冲突,消除在分 E-R 图之间存在的信息冗余,使之成为能够被全系统所有用户共同理解和接受的统一的、精炼的全局概念模型。
合并的方法是将具有相同实体的两个或多个 E-R 图合二为一,在合成后的 E-R 图中把相同实体用一个实体表示,合成后的实体的属性是所有分 E-R 图中该实体的属性的并集,并以此实体为中心,并入其他所有分 E-R 图。再把合成后的 E-R 图以分 E-R 图看待,合并剩余的分 E-R 图,直至所有的 E-R 图全部合并,就构成一张全局 E-R 图。
注意分 E-R 图进行合并时,它们之间存在的冲突主要有以下 3 类。
- 属性冲突。同一属性可能会存在于不同的分 E-R 图中,由于设计人员不同或是出发点不同,对属性的类型、取值范围、数据单位等可能会不一致,这些属性数据将来只能以一种形式在计算机中存储,这就需要在设计阶段进行统一。
- 命名冲突。相同意义的属性,在不同的分 E-R 图上有着不同的命名,或是名称相同的属性在不同的分 E-R 图中代表着不同的意义,这些也需要进行统一。
- 结构冲突。同一实体在不同的分 E-R 图中有不同的属性,同一对象在某一分 E-R 图中被抽象为实体而在另一分 E-R 图中又被抽象为属性。对于这种结构冲突问题需要统一。
分 E-R 图的合并过程中要对其进行优化,具体可以从以下几个方面实现。
- 实体类型的合并。两个具有 1:1 联系或 1:* 联系的实体,可以予以合并,使实体个数减少,有利于减少将来数据库操作过程中的连接开销。
- 冗余属性的消除。一般在各分 E-R 图中的属性是不存在冗余的,但合并后就可能出现冗余。因为合并后的 E-R 图中的实体继承了合并前该实体在分 E-R 图中的全部属性,属性间就可能存在冗余,即某一属性可以由其他属性确定。
- 冗余联系的消除。在分 E-R 图合并过程中,可能会出现实体联系的环状结构,即某一实体 A 与另一实体 B 有直接联系,同时 A 又通过其他实体与实体 B 发生间接联系,通常直接联系可以通过间接联系所表达,可消除直接联系。
6.3.4 逻辑结构设计
逻辑结构设计即是在概念结构设计的基础上进行数据模型设计,可以是层次模型、网状模型和关系模型。逻辑结构设计阶段的主要工作步骤包括确定数据模型、将 E-R 图转换成为指定的数据模型、确定完整性约束和确定用户视图。
1. E-R 图转换为关系模式
E-R 图方法所得到的全局概念模型是对信息世界的描述,并不适用于计算机处理,为适合关系数据库系统的处理,必须将 E-R 图转换为关系模式。E-R 图是由实体、属性和联系三要素构成的,而关系模型中只有唯一的结构——关系模式,通常采用下述方法加以转换。
- 将 E-R 图中的实体逐一转换成为一个关系模式,实体名对应关系模式的名称,实体的属性转换为关系模式的属性,实体标识符就是关系的码。
- E-R 图中的联系有 3 种:一对一联系(1:1)、一对多联系(1:)和多对多联系(:*),针对这 3 种不同的联系,转换方法如下。
- 一对一联系的转换。通常一对一联系不需要将其转换为一个独立的关系模式,只需要将联系归并到关联的两个实体的任一方,给待归并的一方实体属性集中增加另一方实体的码和该联系的属性即可,归并后的实体码保持不变。
- 一对多联系的转换。通常一对多联系也不需要将其转换为一个独立的关系模式,只需要将联系归并到关联的两个实体的多方,给待归并的多方实体属性集中增加一方实体的码和该联系的属性即可,归并后的多方实体的码保持不变。
- 多对多联系的转换。多对多联系只能转换成一个独立的关系模式,关系模式的名称取联系的名称,关系模式的属性取该联系所关联的两个多方实体的码及联系的属性,关系的码是多方实体的码构成的属性组。
2.关系模式规范化
由 E-R 图转换得来的初始关系模式并不能完全符合要求,还会有数据冗余、更新异常存在,这就需要经过进一步的规范化处理,具体步骤如下。
- 根据语义确定各关系模式的数据依赖。在设计的前一阶段,只是从关系及其属性来描述关系模式,并没有考虑到关系模式中的数据依赖。关系模式包含着语义,要根据关系模式所描述的自然语义写出关系数据依赖。
- 根据数据依赖确定关系模式的范式。由关系的码及数据依赖,根据规范化理论,就可以确定关系模式所属的范式,判定关系模式是否符合要求,即是否达到了 3NF 或 BCNF。
- 如果关系模式不符合要求,要根据关系模式的分解算法对其进行分解,使其达到 3NF 或 BCNF。
- 关系模式的评价及修正。根据规范化理论,对关系模式分解之后,就可以在理论上消除冗余和更新异常。但根据处理要求,可能还需要增加部分冗余以满足处理要求,这就需要做部分关系模式的处理,分解、合并或增加冗余属性,提高存储效率和处理效率。
3.确定完整性约束
根据规范化理论确定了关系模式之后,还要对关系模式加以约束,包括数据项的约束、表级约束及表间约束,可以参照 SQL 标准来确定不同的约束,如检查约束、主码约束、参照完整性约束,以保证数据的正确性。
4.确定用户视图
确定了整个系统的关系模式之后,还要根据数据流图及用户信息建立视图模式,提高数据的安全性和独立性。
- 根据数据流图确定处理过程使用的视图。数据流图是某项业务的处理,使用了部分数据,这些数据可能要跨越不同的关系模式,建立该业务的视图,可以降低应用程序的复杂性,并提高数据的独立性。
- 根据用户类别确定不同用户使用的视图。不同的用户可以处理的数据可能只是整个系统的部分数据,而确定关系模式时并没有考虑这一因素,如学校的学生管理,不同的院系只能访问和处理自己的学生信息,这就需要建立针对不同院系的视图来达到这一要求,这样可以在一定程度上提高数据的安全性。
5.反规范化
在关系模式的规范化过程中,会导致关系的概念愈来愈单一化,在响应用户查询时,往往需要涉及多表的关联操作,导致查询性能下降。为此需要对关系模式进行修正,对部分影响性能的关系模式进行处理,包括分解、合并、增加冗余属性等。
这种修正称之为反规范化设计,反规范化 (Denormalization) 是加速读操作性能(数据检索)的方法,一般用这种方法有选择地在数据结构标准化后添加特定的冗余数据实例。反规范化数据库不应该与从未进行过标准化的数据库相混淆。常见的反规范化操作由冗余列、派生列、表重组和表分割,其中表分割又分为水平分割和垂直分割。
反规范化都会在数据库中形成数据冗余,在提高查询性能的同时,也带来设计复杂和更新异常的问题。由于反规范化形成了数据冗余,为解决数据冗余带来的数据不一致性问题,设计人员往往需要额外采用数据同步的方法来解决这种数据不一致性。常见的方法有应用程序同步、批量处理同步和触发器同步等。
6.3.5 物理设计
一般来说,物理设计的主要工作步骤包括确定数据分布、存储结构和访问方式。
1.确定数据分布
从企业计算机应用环境出发,需要确定数据是集中管理还是分布式管理,目前企业内部网及因特网的应用越来越广泛,数据大都采用分布式管理。对于数据如何分布需要从以下几个方面进行考虑。
- 根据不同应用分布数据。企业的不同部门一般会使用不同数据,将与部门应用相关的数据存储在相应的场地,使得不同的场地上处理不同的业务,对于应用多个场地的业务,可以通过网络进行数据处理。
- 根据处理要求确定数据的分布。对于不同的处理要求,也会有不同的使用频度和响应时间,对于使用频度高、响应时间短的数据,应存储在高速设备上。
- 对数据的分布存储必然会导致数据的逻辑结构的变化,要对关系模式作新的调整,需要回到数据库逻辑设计阶段作必要的修改。
2.确定数据的存储结构
存储结构具体指数据文件中记录之间的物理结构。在文件中,数据是以记录为单位存储的,可以采用顺序存储、哈希存储、堆存储和 B 树存储等方式。在实际应用中,要根据数据的处理要求和变更频度选定合理的物理结构。
为提高数据的访问速度,通常会采用索引技术。在物理设计阶段,要根据数据处理和修改要求,确定数据库文件的索引字段和索引类型。
3.确定数据的访问方式
数据的访问方式是由其存储结构所决定的,采用什么样的存储结构,就使用什么样的访问方式。数据库物理结构主要由存储记录格式、记录在物理设备上的安排及访问路径(存取方法)等构成。
- 存储记录结构设计
存储记录结构包括记录的组成、数据项的类型、长度和数据项间的联系,以及逻辑记录到存储记录的映射。在设计记录的存储结构时,并不改变数据库的逻辑结构,但可以在物理上对记录进行分割。数据库中数据项的被访问频率是很不均匀的,基本上符合公认的"80/20 规则",即"从数据库中检索的 80%的数据由其中的 20%的数据项组成"。
当多用户同时访问常用数据项时,往往会因为访盘冲突而等待。若将这些数据分布在不同的磁盘组上,当多用户同时访问常用数据项时,系统可并行地执行 I/O, 从而减少访盘冲突,提高数据库的性能。可见对于常用关系,最好将其水平分割成多个片,分布到多个磁盘组上,以均衡各个磁盘组的负荷,发挥多磁盘组并行操作的优势,提高系统性能。
- 存储记录布局
存储记录的布局,就是确定数据的存放位置。存储记录作为一个整体,如何分布在物理区域上,是数据库物理结构设计的重要环节。采用聚簇功能可以大大提高按聚簇码进行查询的效率。聚簇不但可用于单个关系,也适用于多个关系。
建立聚簇索引的原则如下。
- 聚簇码的值相对稳定,没有或很少需要进行修改。
- 表主要用于查询,并且通过聚簇码进行访问或连接是该表的主要应用。
- 对应每个聚簇码值的平均元组数既不太多,也不太少。
任何事物都有两面性,聚簇对于某些特定的应用可以明显地提高性能,但对于与聚簇码无关的查询却毫无益处。相反地,当表中数据有插入、删除、修改时,关系中有些元组就要被搬动后重新存储,所以建立聚簇的维护代价是很大的。
- 存取方法的设计
存取方法是为存储在物理设备(通常是外存储器)上的数据提供存储和检索的能力,是快速存取数据库中数据的技术。存取方法包括存储结构和检索机制两部分。其中存储结构限定了可能访问的路径和存储记录;检索机制定义了每个应用的访问路径。数据库系统是多用户共享系统,对同一个关系建立多条存取路径才能满足多用户的多种应用要求。为关系建立多种存取路径是数据库物理设计的任务之一。
在数据库中建立存取路径最普遍的方法是建立索引。确定索引的一般顺序如下。
- 首先可确定关系的存储结构,即记录的存放是无序的,还是按某属性(或属性组)聚簇存放。这在前面已讨论过,这里不再重复。
- 确定不宜建立索引的属性或表。对于太小的表、经常更新的属性或表、属性值很少的表、过长的属性、一些特殊数据类型的属性(大文本、多媒体数据)和不出现或很少出现在查询条件中的属性不宜建立索引。
- 确定宜建立索引的属性。例如,关系的主码或外部码、以查询为主或只读的表、范围查询、聚集函数 (Min、Max、Avg、Sum、Count) 或需要排序输出的属性可以考虑建立索引。
索引一般还需在数据库运行测试后,再加以调整。在 RDBMS 中,索引是改善存取路径的重要手段。使用索引的最大优点是可以减少检索的 CPU 服务时间和 I/O 服务时间,改善检索效率。但是,不能对进行频繁存储操作的关系建立过多的索引,因为过多的索引也会影响存储操作的性能。
6.3.6 数据库实施
根据逻辑和物理设计的结果,在计算机上建立起实际的数据库结构,数据加载(或称装入),进行试运行和评价的过程,叫作数据库的实施(或称实现)。
1.建立实际的数据库结构
用 DBMS 提供的数据定义语言 (DDL) 编写描述逻辑设计和物理设计结果的程序(一般称为数据库脚本程序),经计算机编译处理和执行后,就生成了实际的数据库结构。所用 DBMS 的产品不同,描述数据库结构的方式也不同。有的 DBMS 提供数据定义语言,有的提供数据库结构的图形化定义方式,有的两种方法都提供。在定义数据库结构时,应包含以下内容。
- 数据库模式与子模式,以及数据库空间等的描述。例如,在 Oracle 系统中,数据库逻辑结果的描述包括表空间 (Tablespace)、段 (Segment)、范围 (Extent) 和数据块 (Data block)。DBA 或设计人员通过对数据库空间的管理和分配,可以控制数据库中数据的磁盘分配,将确定的空间份额分配给数据库用户,能够控制数据的可用性,将数据存储在多个设备上,以此提高数据库性能等。
- 数据库完整性描述。所谓数据的完整性,是指数据的有效性、正确性和一致性。在数据库设计时,如果没有一定的措施确保数据库中数据的完整性,就无法从数据库中获得可信的数据。数据的完整性设计,应该贯穿在数据库设计的全过程中。例如,在数据需求分析阶段,收集数据信息时,应该向有关用户调查该数据的有效值范围。在模式与子模式中,可以用 DBMS 提供的 DDL 语句描述数据的完整性。
- 数据库安全性描述。数据安全性设计同数据完整性设计一样,也应在数据库设计的各个阶段加以考虑。在进行需求分析时,分析人员除了收集信息及数据间的联系之外,还必须收集关于数据的安全性说明。在设计数据库逻辑结构时,对于保密级别高的数据,可以单独进行设计。子模式是实现安全性要求的一个重要手段,可以为不同的应用设计不同的子模式。在数据操纵上,系统可以对用户的数据操纵进行两方面的控制:一是给合法用户授权,目前主要有身份验证和口令识别;二是给合法用户不同的存取权限。
- 数据库物理存储参数描述。物理存储参数因 DBMS 的不同而不同。一般可设置的参数包括块大小、页面大小(字节数或块数)、数据库的页面数、缓冲区个数、缓冲区大小和用户数等。详细内容请参考 DBMS 的用户手册。
2.数据加载
数据库应用程序的设计应该与数据库设计同时进行。一般地,应用程序的设计应该包括数据库加载程序的设计。在数据加载前,必须对数据进行整理。由于用户缺乏计算机应用背景知识,常常不了解数据的准确性对数据库系统正常运行的重要性,因而未对提供的数据作严格的检查。所以,数据加载前要建立严格的数据登录、录入和校验规范,设计完善的数据校验与校正程序,排除不合格数据。
数据加载分为手工录入和使用数据转换工具两种。现有的 DBMS 都提供了 DBMS 之间数据转换的工具。如果用户原来就使用数据库系统,可以利用新系统的数据转换工具。先将原系统中的表转换成新系统中相同结构的临时表,然后对临时表中的数据进行处理后插入到相应表中。数据加载是一项费时费力的工作。另外,由于还需要对数据库系统进行联合调试,所以大部分的数据加载工作应在数据库的试运行和评价工作中分批进行。
3.数据库试运行和评价
当加载了部分必须的数据和应用程序后,就可以开始对数据库系统进行联合调试,称为数据库的试运行。一般将数据库的试运行和评价结合起来的目的是测试应用程序的功能;测试数据库的运行效率是否达到设计目标,是否为用户所容忍。测试的目的是为了发现问题,而不是为了说明能达到哪些功能。所以,测试中一定要有非设计人员的参与。
用户数据可能是以前旧系统的数据,并不完全满足新系统的数据要求,需要进行处理,同时还要做好新系统的数据库的转储和恢复工作,以免发生故障时丢失数据。
6.3.7 数据库运行维护
数据库一旦投入运行,就标志着数据库维护工作的开始。数据库维护工作的主要内容包括对数据库性能的监测和改善、故障恢复、数据库的重组和重构。在数据库运行阶段,对数据库的维护主要由 DBA 完成。
1.对数据库性能的监测和改善
性能可以用处理一个事务的 I/O 量、CPU 时间和系统响应时间来度量。由于数据库应用环境、物理存储的变化,特别是用户数和数据量的不断增加,数据库系统的运行性能会发生变化。某些数据库结构(如数据页和索引)经过一段时间的使用以后,可能会被破坏。所以,DBA 必须利用系统提供的性能监控和分析工具,经常对数据库的运行、存储空间及响应时间进行分析,结合用户的反映确定改进措施。目前的 DBMS 都提供一些系统监控或分析工具。例如,在 SQL Server 中使用 SQL Server Profiler 组件、Transaction-SQL 工具和 Query Analyzer 组件等都可进行系统监测和分析。
2.数据库的备份及故障恢复
数据库是企业的一种资源,所以在数据库设计阶段,DBA 应根据应用要求制定不同的备份方案,保证一旦发生故障能很快地将数据库恢复到某种一致性状态,尽量减少损失。数据库的备份及故障恢复方案,一般基于 DBMS 提供的恢复手段。
3.数据库重组和重构
数据库运行一段时间后,由于记录的增、删、改,数据库物理存储碎片记录链过多,影响数据库的存取效率。这时,需要对数据库进行重组和部分重构。数据库的重组是指在不改变数据库逻辑和物理结构的情况下,去除数据库存储文件中的废弃空间以及碎片空间中的指针链,使数据库记录在物理上紧连。
数据库系统运行过程中,会因为一些原因而对数据库的结构做修改,称为数据库重构。重构包括表结构的修改和视图的修改。表结构的修改有数据列的增删和修改、约束的修改、表的分解与合并。需要注意的是 DBMS 有一定的逻辑独立性,某些修改可能不需要修改应用程序,以减少系统运维的代价。
视图机制的优点是可以实现数据的逻辑独立性,并且可以实现数据的安全性。采用视图机制可将不允许应用程序访问的数据屏蔽在视图之外。但是在数据库重构过程中引入或修改视图,可能会影响数据的安全性,所以必须对视图进行评价和验证,保证不能因为数据库的重构而引起数据的泄密。
6.4 应用程序与数据库的交互
在普通的情况下,用户可以通过 SQL 和过程性 SQL (如 PL/SQL、T-SQL 等)来访问数据库中的数据。但是在应用系统中,需要高级程序语言来完成与用户之间的交互,用户不能直接访问后台的数据库。因此数据库管理系统需要提供程序级别的接口来访问数据。常见应用程序与数据库的数据交互方式有库函数、嵌入式 SQL、通用数据接口标准和对象关系映射 (Object Relational Mapping,ORM) 等。
6.4.1 库函数级别访间接口
库函数级别的数据访问接口往往是数据库提供的最底层的高级程序语言访问数据接口,如 Oracle 数据库的 Oracle Call Interface(OCI)。开发者可以使用高级程序语言编写程序实现人机交互和业务逻辑,而使用 OCI 来访问数据库。
OCI 是由一组应用程序开发接口 (API) 组成的,Oracle 提供 API 的方式是提供一组库。这组库包含一系列的函数调用。这组函数包含了连接数据库、调用 SQL 和事务控制等。在安装 DBMS Server 或者客户端的时候,就安装了 OCI。
OCI 开发方法实际上是将结构化查询语言 (SQL) 和高级程序语言相结合的一种方法。对数据库的访问是通过调用 OCI 库函数实现的,若将 C 语言作为宿主语言,那么 Oracle 数据库调用其实就是 C 程序中的函数调用,一个含 OCI 调用的 C 程序其实就是用 C 语言编写的应用程序。这样的程序既具有 SQL 语言非过程性的优点又具有 C 语言过程性的优点,同时还可具有 SQL 语言的扩展,PL/SQL 语言过程性和结构性的优点,因此使得开发出的应用程序具有高度灵活性。
OCI 开发方法的缺点是往往强依赖于特定的数据库,需要数据库开发人员对该数据库机制有较深的理解,学习难度较大,开发效率不是很高。
6.4.2 嵌入SQL访问接口
嵌入式 SQL(Embedded SQL) 是一种将 SQL 语句直接写入某些高级程序语言,如 C、COBOL、Java、Ada 等编程语言的源代码中的方法。借此方法,可使得应用程序拥有了访问数据以及处理数据的能力。
在 SQL86 规范中定义了对于 COBOL、FORTRAN、PI/L 等语言的嵌入式 SQL 的规范。在 SQL89 规范中,定义了对于 C 语言的嵌入式 SQL 的规范。一些大型的数据库厂商发布的数据库产品中,都提供了对于嵌入式 SQL 的支持,如 Oracle、DB2 等。
在这一方法中,将 SQL 文嵌入的目标源码的语言称为宿主语言。
提供对于嵌入式 SQL 的支持,需要数据库厂商除了提供 DBMS 之外,还必须提供一些工具。为了实现对于嵌入式 SQL 的支持,技术上必须解决以下问题。
- 宿主语言的编译器不能识别和接受 SQL 程序,需要解决如何将 SQL 的宿主语言源代码编译成可执行码。
- 宿主语言的应用程序如何与 DBMS 之间传递数据和消息。
- 如何把对数据的查询结果逐次赋值给宿主语言程序中的变量,以供其处理。
- 数据库的数据类型与宿主语言的数据类型有时不完全对应或等价,如何解决必要的数据类型转换问题。
为了解决上述这些问题,数据库厂商需要提供一个嵌入式 SQL 的预编译器,把包含有嵌入式 SQL 的宿主语言源码转换成纯宿主语言的代码。这样一来,源码即可使用宿主语言对应的编译器进行编译。通常情况下,经过嵌入式 SQL 的预编译之后,原有的嵌入式 SQL 会被转换成一系列函数调用。因此,数据库厂商还需要提供一系列函数库,以确保链接器能够把代码中的函数调用与对应的实现链接起来。
嵌入式 SQL 中除了可以执行标准 SQL 程序之外,为了对应嵌入的需要,还增加了一些额外的语法成分。主要包括宿主变量使用声明、数据库访问、事务控制、游标操作的语法等。
6.4.3 通用数据接口标准
开放数据库连接 (Open DataBase Connectivity,ODBC) 是为解决异构数据库间的数据共享而产生的。ODBC 为异构数据库访问提供统一接口,允许应用程序以 SQL 为数据存取标准,存取不同 DBMS 管理的数据;使应用程序直接操纵数据库中的数据,免除随数据库的改变而改变,也可以访问如 Excel 表和 ASCII 数据文件这类非数据库对象。
一个基于 ODBC 的应用程序对数据库进行操作时,用户直接将 SQL 语句传送给 ODBC, 同时 ODBC 对数据库的操作也不依赖任何 DBMS, 不直接与 DBMS 打交道,所有的数据库操作由对应的 DBMS 的 ODBC 驱动程序完成,由对应 DBMS 的 ODBC 驱动程序对 DBMS 进行操作。也就是说,不论哪种数据库系统,均可用 ODBC API 进行访问。ODBC 的最大优点就是能以统一的方式处理所有的关系数据库。
在具体操作时,首先必须用 ODBC 管理器注册一个数据源,管理器根据数据源提供的数据库位置、数据库类型及 ODBC 驱动程序等信息,建立起 ODBC 与具体数据库的联系。这样,只要应用程序将数据源名提供给 ODBC,ODBC 就能建立起与相应数据库的连接。
直接使用 ODBC API 比较麻烦,微软后来又发展出来 DAO、RDO、ADO 这些数据库接口,使用这些数据库接口开发程序更容易。
- 数据库访问对象 (Database Access Object,DAO), 就是因素与数据库打交道的,位于业务逻辑层与数据资源层之间,是微软的一种用来访问 Jet 引擎的方法,主要适用于单系统应用程序或在小范围本地分布使用,访问桌面数据库(如 Access、FoxPro、dBase 等)。
- 远程数据库对象 (Remote Database Object,RDO)。为了弥补 DAO 访问远程数据库能力的不足,微软推出了 RDO 数据库访问接口,可以方便地用来访问远程数据库。它封装了 ODBC API 的对象层,因此在访问 ODBC 兼容数据库时,具有比 DAO 更高的性能,而且比 ODBC 更易用。
- ActiveX 数据对象 (ActiveX Data Objects,ADO) 是 Microsoft 提出的应用程序接口,用以实现访问关系或非关系数据库中的数据。ADO 从原来的 RDO 而来。RDO 与 ODBC 一起工作访问关系数据库,但不能访问如 ISAM 和 VSAM 的非关系数据库。ADO 是对微软所支持的数据库进行操作的最有效、最简单和最直接的方法,使得大部分数据源可编程的属性得以直接扩展到 Active Server 页面上。可以使用 ADO 去编写紧凑、简明的脚本以便连接到 ODBC 兼容的数据库和 OLE DB 兼容的数据源,这样 ASP 程序员就可以访问任何与 ODBC 兼容的数据库,包括 MS SQL Server、Access、Oracle 等。
ADO.NET 是微软在 .NET 框架下开发设计的一组用于和数据源进行交互的面向对象类库。ADO.NET 提供了对关系数据、XML 和应用程序的访问,允许和不同类型的数据源以及数据库进行交互。
Java 数据库连接 (Java Database Connectivity,JDBC) 是 Java 语言中用来规范客户端程序如何访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC 是一种用于执行 SQL 语句的 Java API, 可以为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。
JDBC 用于直接调用 SQL 命令,被设计为一种基础接口,在它之上可以建立高级接口和工具。
6.4.4 ORM访问接口
对象关系映射 (Object Relational Mapping, 简称 ORM 或 O/RM 或 O/R mapping) 是一种程序设计技术,用于实现面向对象编程语言里不同类型系统数据之间的转换。
ORM 是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射;ORM 可以解决数据库与程序间的异构性。
ORM 是一种将内存中的对象保存到关系型数据库中的技术,主要负责实体域对象的持久化,封装数据库访问细节,提供了实现持久化层的另一种模式,采用映射元数据 (XML) 来描述对象-关系的映射细节,使得 ORM 中间件能在任何一个应用的业务逻辑层和数据库之间充当桥梁。
从软件开发效率上来讲,ORM 的使用也降低了程序员数据库知识的要求。在编程过程中,程序员只须考虑对象即可,无须关心数据库中的数据模式以及对应的 SQL 语句。目前在 Java 语言环境中,典型的 ORM 框架有 Hibernate、Mybatis 和 JPA 等。
- Hibernate: 全自动的框架,强大、复杂、笨重、学习成本较高。
- Mybatis: 半自动的框架。
- JPA(Java Persistence API):JPA 通过 JDK 5.0 注解或 XML 描述对象-关系表的映射关系,是 Java 自带的框架。
6.5 NoSQL数据库
NoSQL 最常见的解释是 Non-Relational,Not Only SQL 也被很多人接受。NoSQL 仅仅是一个概念,泛指非关系型的数据库,区别于关系数据库,它们不保证关系数据的 ACID 特性。
6.5.1 分类与特点
当前出现了很多不同类型、面向不同应用的 No SQL 产品,按照所使用的数据结构的类型,一般可以将 NoSQL 数据库分为以下 4 种类型。
1.列式存储数据库
行式数据库即传统的关系型数据库,数据按记录存储,每一条记录的所有属性存储在一行。列式数据库是按数据库记录的列来组织和存储数据的,数据库中每个表由一组页链的集合组成,每条页链对应表中的一个存储列。
这类数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。现有产品如 Cassandra、HBase、Riak。
2.键值对存储数据库
键值存储的典型数据结构一般为数组链表:先通过 Hash 算法得出 Hashcode, 找到数组的某一个位置,然后插入链表。
这类数据库主要会用到一个哈希表,表中有一个特定的键和一个指针指向特定的数据。Key-value 模型对于 IT 系统来说,其优势在于简单、易部署。但是如果数据库管理员只对部分值进行查询或更新的时候,Key-value 就显得效率低下了。现有产品如 Tokyo Cabinet/Tyrant、Redis、Voldemort、Oracle BDB。
3.文档型数据库
文档型数据库同键值对存储数据库类似。文档型数据库的灵感来自于 Lotus Notes 办公软件,而且它同键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如 JSON。文档型数据库可以看作是键值数据库的升级版,允许嵌套键值,在处理网页等复杂数据时,文档型数据库比传统键值数据库的查询效率更高。现有产品如 CouchDB、MongoDb, 国内也有文档型数据库 SequoiaDB, 已经开源。
4.图数据库
图形结构的数据库同其他采用行列以及刚性结构的 SQL 数据库不同,它使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL 数据库没有标准的查询语言 (SQL), 因此进行数据库查询需要指定数据模型。许多 NoSQL 数据库都有 REST 式的数据接口或者查询 API。适合存储通过图进行建模的数据,例如社交网络数据,生物信息网络数据,交通网络数据等。常见的产品有 Neo4J、InfoGrid、Infinite Graph 等。
目前业界对于 NoSQL 并没有一个明确的范围和定义,但是它们普遍存在下面一些共同特征:
- 易扩展:去掉了关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。
- 大数据量,高性能:NoSQL 数据库都具有非常高的读写性能,尤其在大数据量下。这得益于它的无关系性,数据库的结构简单。
- 灵活的数据模型:NoSQL 无须事先为要存储的数据建立字段,随时可以存储自定义的数据格式。
- 高可用:NoSQL 在不太影响性能的情况下,就可以方便地实现高可用的架构,有些产品通过复制模型也能实现高可用。
6.5.2 体系框架
NoSQL 整体框架分为 4 层,由下至上分为数据持久层 (Data Persistence)、数据分布层 (Data Distribution Model)、数据逻辑模型层 (Data Logical Model) 和接口层 (Interface), 层次之间相辅相成,协调工作。
- 数据持久层定义了数据的存储形式,主要包括基于内存、硬盘、内存和硬盘接口、订制可插拔 4 种形式。基于内存形式的数据存取速度最快,但可能会造成数据丢失;基于硬盘的数据存储可能保存很久,但存取速度慢于基于内存形式的数据;内存和硬盘相结合的形式,结合了前两种形式的优点,既保证了速度,又保证了数据不丢失;订制可插拔则保证了数据存取具有较高的灵活性。
- 数据分布层定义了数据是如何分布的,相对于关系型数据库,NoSQL 可选的机制比较多,主要有 3 种形式:一是 CAP 支持,可用于水平扩展;二是多数据中心支持,可以保证在横跨多数据中心时也能够平稳运行;三是动态部署支持,可以在运行着的集群中动态地添加或删除结点。
- 数据逻辑层表述了数据的逻辑表现形式。
- 接口层为上层应用提供了方便的数据调用接口,提供的选择远多于关系型数据库。接口层提供了 5 种选择:Rest、Thrift、Map/Reduce、Get/Put、特定语言 API, 使得应用程序和数据库的交互更加方便。
NoSQL 分层架构并不代表每个产品在每一层只有一种选择。相反,这种分层设计提供了很大的灵活性和兼容性,每种数据库在不同层面可以支持多种特性。
NoSQL 数据库在以下这几种情况比较适用:
- 数据模型比较简单;
- 需要灵活性更强的 IT 系统;
- 对数据库性能要求较高;
- 不需要高度的数据一致性;
- 对于给定 key, 比较容易映射复杂值的环境。