数据库是整个应用的根基,没有坚实的根基,整个应用也就岌岌可危了。现代数据库有很多方便设计数据库的工具,但很难帮你解决数据库的逻辑和结构问题,而逻辑和结构 却是数据库设计中极其重要的部分。而保证逻辑和结构良好的设计的基石是对数据库的详尽了解,那么让我们从数据库基础开始吧。
- 数据库概述
- 关系数据库
- 关系数据库标准语言 SQL
- 查询优化
- 数据库的完整性
- 层次与网状数据库系统
- 数据库设计
- 关系数据理论
数据库概述
在设计数据库之前,了解数据库的历史发展,理解数据库的基本概念、熟悉数据模型、基本原理以及如何使用这些概念是非常重要的。这一章节就是给出一张宏观的图纸,建构 起对数据库的轮廓,属于森林级别的论述。
数据管理技术的发展
数据管理指的是如何对数据进行分类、组织、储存、检索及维护。要注意,这里所说的数据,不仅是数字。还包括文字、图形、声音等。凡是计算机中用来描述事物的记录, 统称为数据。
随着计算机软硬件的发展,数据管理技术不断地完善,经历了如下三个阶段:
- 人工管理阶段;
- 文件系统阶段;
- 数据库系统阶段。
人工管理阶段
最初,计算机主要用于科学计算。那时的计算机硬件方面,外存只有卡片、纸带及磁带,没有磁盘等直接存取的存储设备;软件方面,只有汇编语言,没有操作系统和高级语言, 更没有管理数据的软件;数据处理的方式批处理。这些决定了当时的数据管理职能依赖人工来进行。
人工管理阶段的特点是:
(1)数据不保存,一组数据对应一个应用程序,应用程序与其处理的数据结合成一个整体,在进行计算时,系统将应用程序和数据一起装入,程序运行结束后, 释放内存空间,程序和数据同时被撤销。
(2)没有软件对数据进行管理。应用程序设计者不仅要考虑数据之间的逻辑关系,还要考虑存储结构、存取方法以及输入方式等。如果存储结构发生变化, 读写数据的程序也要发生改变,数据没有独立性。
(3)没有文件概念。数据的组织方法由程序设计人员自行设计和安排。
(4)数据面向应用。数据附属于程序,即使两个应用程序使用相同的数据,也必须各自定义数据的存储和存取方式,不能共享相同的数据定义, 因此程序与程序之间可能有大量的重复数据。
文件系统阶段
后来,计算机不仅用于科学计算,也大量用于经营管理活动。硬件设备有了硬盘、磁鼓等直接存储设备;软件发展了操作系统和各种高级语言。 人们可以将应用程序所需的大量数据组织成一个数据文件长期保存在直接存储设备上,利用操作系统中的文件管理随时可以对文件中的数据进行存取, 并且只需要知道相应的文件名即可实现按名存取。
在文件系统阶段数据管理具有以下特点:
(1)数据可长期保存在磁盘上,用户可通过程序对文件进行查询、修改、插入或删除操作。
(2)文件系统提供程序和数据之间的读写方法。文件管理系统管理是应用程序与数据文件之间的一个接口。应用程序通过文件管理系统建立和存储文件;反之, 应用程序要存取文件中的数据,必须通过文件管理系统实现。用户不必关心数据的物理位置,程序和数据之间有了一定的独立性。
(3)文件形式多样化。因为有了直接存储设备,所以可以建立索引文件、链接文件和直接存取文件等。对文件的记录可顺序访问和随机访问。文件之间是相互独立的, 文件与文件之间的联系需要用程序来实现。
(4)数据的存取基本上以记录为单位。
但文件系统阶段数据管理存在如下缺陷:
- 数据冗余大,因为文件是为特定的用途设计的,因此会造成数据在多个文件中被重复存储。
- 数据的不一致。这是由于数据冗余和文件之间的独立性造成的,在更新数据时,很难保证同一数据在不同文件中的一致。
- 程序与数据之间的独立性差。修改文件的存储结构后,相关的程序也要被修改。
数据库管理阶段
存储技术有了很大的发展,产生了大容量磁盘。计算机用于管理的规模更加庞大,数据量急剧增长, 原有文件系统的固有缺陷使之不能满足大量应用和用户对数据的共享性和安全性等需求。为了提高效率,人们着手开发和研制更加有效的数据管理模式, 并由此提出了数据库的概念。
在数据库管理与文件管理相比数据库技术有了很大的改进,主要表现在以下方面:
(1)数据库中的数据是结构化的。在文件系统中,数据是无结构的,即不同文件中的记录之间没有联系,它只在数据项之间有联系。数据库系统不仅考虑数据项之间的联系, 还要考虑记录之间的联系,这种联系是通过存储路径来实现的。
(2)数据库中的数据时面向系统的,对于任何一个系统来说,数据库中的数据结构式透明的,任何应用程序都可以通过标准化接口访问数据库。
(3)数据库系统比文件系统有较高的数据独立性,而且共享性好。
(4)数据库系统为用户提供了方便统一的接口。用户可以用数据系统提供的查询语言和交互式命令操作数据库。用户也可以用高级语言编写程序来访问数据库, 扩展了数据库的应用范围。
(5)数据存取粒度小。文件系统中,数据存取的最小单位是记录;而在数据库系统中,数据存取的粒度可以小到记录中的一个数据项。因此数据库中数据存取的方式非常灵活, 便于对数据的管理。
与此同时,数据库技术的发展是数据管理上了一个新台阶,在数据完整性、安全性、并发控制和数据恢复方面,数据管理系统都提供了非常完善的功能选择,同时为用户提供了 友好的接口。
数据库类型(模型)
上一节简单讲解了数据管理技术的历史,自从进入数据库阶段之后,经过不断的发展,目前主要出现了以下几种数据库类型(模型):
- 平面文件数据库模型;
- 层次数据库模型;
- 网状数据库模型;
- 关系数据库模型;
- 面向对象数据库模型;
- 对象关系数据库模型。
理想数据库应该具有以下特征:
- 充足的容量;
- 足够的安全和审核;
- 多用户环境;
- 效率和查找能力;
- 可伸缩性;
- 用户友好。
数据库管理系统(DBMS)
数据库管理系统是用来存储数据的软件产品。软件开发商根据特定的数据库模型设计出不同的 DBMS 系统。DBMS 系统应该具备如下一些特点:
- 数据持久性:数据存储在硬件设备上并且在被访问后仍然存在。数据访问方法包括新数据的创建、现有数据的修改以及数据的删除。
- 并发性: 控制多用户的并发访问,保证并发访问不相互影响,不损坏数据。
- 事务管理:支持数据操作以及能够保存批量工作的能力。
- 可以使用基于用户提供查询条件检索数据的查询语言。
- 数据可以从失败的事务中恢复。如果出现数据丢失,DBMS 应该具有能够根据各种情况恢复数据的能力。
平面文件数据库模型
平面文件数据库由一个或多个可读文件组成,这些文件通常按照文本的格式保存。这些文件中的信息按域来保存,这些域可以有固定长度,也可以是变长的,并且域之间通过 一些特殊符号(分界符)来分隔,从而必须保证分界符不会出现在数据中。
由于不同的公司需要存储不同的数据且具有不同的数据需求,因此每一个平面文件数据库系统都是各不相同的。创建一个平面文件数据库并存储数据后,应该设计检索数据、 创建新记录、更新记录以及删除记录的方法。
在普通文件中,访问数据的问题是,必须设计一系列的程序来查询存储在普通文件中的信息。如果没有这些方法,用户或客户就必须自己来查询这些文件,这显然是不能接受的。
平面文件数据库系统最主要的问题是:
不但要掌握这些普通文件的结构,还要知道这些数据的物理存储位置。此外,这种数据库系统还可能会需要大量的普通文件,因为相关数据可能会保存在不同的文件中。在 平面文件数据库环境中,对数据联系的管理是一项非常困难的任务。
平面数据库系统的缺点:
- 普通文件无法提供便于数据关联的结构;
- 不能有效地管理数据并保证数据的准确性;
- 通常必须存储冗余数据,这导致了准确维护数据的额外工作量;
- 必须知道文件中数据域的物理存储位置;
- 必须设计管理数据的程序。
层次数据库模型
相对平面文件数据库而言,层次数据库可以创建和维护不同类别数据之间的关联关系。层次数据库的体系结构是基于父/子关系的,就像一颗倒转的树。
父表可以有多个子表,但子表只能有一个父表。要访问一个字表,必须首先访问父表。分层结构中的关联表是通过指针连接的,指针直接指向子记录的物理位置。
相对平面文件数据库模型,层次数据库模型具有如下一些优点:
- 快速的数据查询;
- 便于管理数据的完整性。
但层次数据库也存在如下缺点:
- 用户必须时分熟悉数据库结构,任何访问必须从根节点开始;
- 需要存储存储荣誉数据(以表示那些没有直接关联关系的表之间的逻辑关系),
层次数据库在处理一对多关系时表现得很好,但很难表示多对多关系(因为层次数据库子表只允许有一个父表)。
网状数据库模型
网状数据库相对于层次数据库,一个最主要的优点就是允许父表和子表之间共享关联关系。这意味着子表可以有多个父表。此外,用户可以从网状模型的任何表开始访问数据。 在树形结构中支持向上和向下访问方式。用户不在需要从根表开始来访问某个子表。
网状数据库模型的优点是:
- 快速的数据访问;
- 用户可以从任何表开始访问其他表数据;
- 便于复杂数据库的建模;
- 便于开发更复杂的查询来检索数据。
网状数据库模型的缺点是:
- 不便于数据库结构的修改;
- 数据库结构的修改将直接影响访问数据库的应用程序;
- 用户必须掌握数据库结构。
尽管网状数据库模型具备一些优势,但其还是存在几个层次数据库同样的问题。二者都不具备灵活性,任何对结构的改变都需要重建整个数据库;同样,集合关系和记录结构 都必须预先定义。
网状和层次数据库的主要劣势是它们都是程序员领域。要回应一个最简单的查询,也不得不创建一个程序,这个程序定位数据库结构并最终输出结果;不同于 SQL,这个程序是 用程序化语言写成的,这些程序化语言常常都是一些归各个公司所有的专利语言,同时,使用者还需要具备数据库结构和当前操作系统两方面的深厚只是。毫无疑问,这样的 程序不具有可移植性,而且编写这些程序将花费大量的时间。
关系数据库
与层次和网状模型相同,关系型模型是基于二维存储空间(表)的,这些表基于共有的一个字段(或一系列字段)而相互关联。然而,这种关系式由列值来实现的,而不像以往 是由低级的物理指针来定义。
数据库中数据存储的主要载体是表
(所谓的“关系”),或相关数据组。表由行和列组成。在表中,一行表示一条数据记录。一列表示所有数据记录在该特定域的值。表之间
通过公共列值实现关联关系,这样的列也叫关键字
。
关系数据库模型支持三种类型的表关联关系:一对一、一对多以及多对多,数据库应该支持这些不同类型的表间联系。表关联
是通过引用完整性定义的,这些完整性又是
通过主码和外码(或称为“外键”)约束条件实现的。应用完整性是通过这些约束条件来校验进入表中的数据并且管理父、子表之间的关系的。其他类型的约束条件也可以用来
控制表的特定列数据以及创建表之间的联系。
在关系模型中,虽然还支持父表和子表之间的关系,但已经没有了根表。父表可以有多个子表,子表也可以有多个父表(它们之间是双向的关系)。
关系数据库中的对象
在关系数据库中有许多类型的对象。如下所列的是关系数据库中通用的对象:
- 表:
表是关系数据库中数据存储的主要对象。查询和修改数据操作通常是在表中进行的。表通过多个列来定义。所有列上的一行数据叫做一个数据行(数据记录)。
- 视图:
视图是虚拟表,它具有表的特性。视图
是根据表的数据以及结构所定义的。视图可以查询,有时也可以进行数据更新。
- 约束:
约束
是放置数据规则的对象。它可以用来控制列中的数据。约束通常定义在列一级,它也可以用来加强引用完整性(父/子表之间的联系)。
- 索引:
索引
是用来加速数据检索的对象。索引的每一条记录都指向表中相应的数据记录,类似于图书的目录执行特定的页面。
- 触发器:
触发器
是数据库中用来保存程序代码的对象,它是由数据库中发生的特定时间而出发执行的。当一个触发器被触发时,数据可以根据其他被访问或修改的数据而
被相应修改。触发器对减少冗余数据非常有用。
- 过程:
也叫做存储过程
。它是保存在数据库中的程序。在数据库中,存储过程是可以执行的。过程通常用来管理数据和进行批处理操作。
以上介绍的前四个对象是与数据库定义相关的对象,而后两个对象则是访问数据库对象的方法。关系数据库中对象为用户提供了逻辑表现形式,这样使数据的物理位置对 用户来说是不重要的。
关系数据库模型的优点:
- 数据访问非常快;
- 便于修改数据库结构;
- 逻辑化表示数据,因此用户不需要知道数据是如何存储的;
- 容易设计复杂的数据查询来检索数据;
- 容易实现数据完整性;
- 数据通常具有更高的准确性(因为冗余数据更少,从而一致性好);
- 支持标准 SQL 语言。
关系数据库模型的缺点:
- 在很多情况下,必须将多个表的不同数据关联起来实现数据查询;
- 用户必须熟悉表之间的关联关系;
- 用户必须掌握 SQL 语言。
面向对象数据库模型(OODM)
数据库的数据模型一般由三部分组成,它们是:
- 数据模式(数据结构);
- 建立在模式上的操作;
- 数据的完整性约束。
在面向对象数据模型中,我们用面向对象方法中的一些基本概念和基本方法表示这三个组成部分:对象
、方法
、类的继承与合成
。
我们首先用关系模型来解释数据模型中的这三个部分,然后再与面向对象数据模型进行对比。
关系数据模型组成部分
- 关系模型的数据结构是
二维表
;
- 关系模型上的数据操作:查询、插入、删除、修改
- 关系模型上的数据完整性约束:
面向对象数据模型(OODM)组成部分
- OODM 的数据结构:
类层次结构
- 对象:由一组属性、一组方法和一个对象标识符 OID 所构成的一个封装体。
- 类:具有相同属性和相同方法的一组对象的集合;
- 类层次结构:由类与类之间的继承关系和合成关系所构成的一个层次关系图。
- OODM 的数据操作:
方法
与消息
- OODM 的数据约束:
方法
与消息
- 实体完整性:无
- 引用完整性:无
- 用户自定义完整性约束条件:完整性约束方法。
面向对象数据模型就是一个由类及类的继承与合成关系所构成的类层次结构图。例如:
OO 模型与关系模型的对应关系:
OO 模型对关系模型的扩充:
- OID 比主关键字更具有一般性;
- 在对象与类中增加了方法,系统具有更好的稳定性、可扩充性,便于用户使用;
- 丰富的数据类型:类可以看成一种扩充的数据类型;
- 数据模型上的操作更为丰富;
- 数据模型具有更丰富的语义含义。
OODM 的新概念:元类
- 类本身也可以被看成是一种特殊的对象,我们称其为
类对象
。 - 所有类对象的集合也构成一个类,我们称其为
元类
。- 元类中的实例就是传统意义上的类,元类中的方法则是传统意义上的消息。
- 元类实际上就是 OODBS 的数据字典。
面向对象数据库管理系统(OODBMS)除了具有面向对象的概念与方法外,还必需具有传统数据库管理系统的所有功能,是面向对象技术与传统数据库技术的结合体。
在 OODM 中,目前所用的语言大多选用类 SQL 形式,其中较为著名的有:SQL-3
和OQL 语言
。
对象-关系数据库
为了弄清楚对象-关系数据库
所处的地位,先看下面的 DBMS 分类矩阵:
可见,对象-关系数据库是下一个大浪潮。
对象-关系数据模型的特点:
- 通过引入面向对象及处理复杂数据类型的构造来扩展关系数据模型;
- 允许元组属性具有复杂类型,包括非原子值(如嵌套关系);
- 保持关系基础,尤其是对数据描述性存取,同时扩展建模能力;
- 与现有关系向上兼容。
嵌套关系
允许非原子域(原子 = 不可分割),非原子域可以是整数集合、原子集合等。如此,使含有复杂数据的应用可以更直观地建模。
嵌套关系的特点:
- 在原先只允许出现原子值(标量)的地方可以出现关系(即
关系内关系
); - 保持关系模型的数学基础;
- 违反第一范式。
注意事项:
对象-关系数据模型很不成熟,还处于争议阶段(虽然有的厂商已经推出了不成熟的产品)。有的人认为大部分厂商和学者犯了一下错误:
(1)第一个错误是将对象类与关系变量等同(不幸的是,这一等式在表面上非常吸引人)。我们猜测这一错误来自对术语“对象”两种不同理解的混淆。
(2)第二个根本性错误!—即将指针与关系相混淆(当然不犯第一个错误的系统也可能犯第二个错误,并且目前市场上几乎每一个产品都犯有这一错误)。我们认为, 第二个根本性错误在许多方面削弱了关系模型的概念完整性。具体来说,它破坏了基本关系与导出关系之间的可交换性原则。
数据库基本概念
数据库、数据库管理系统和数据库系统经常被作为同义词使用。严格地讲,它们是三个不同的概念:
数据库
数据库是相互关联的数据集合。数据是描述显示世界中各种具体事务或抽象概念的可存储并具有明确意义的信息。*相互关联并且可存储的数据集合并定义为数据库
*。
数据库的特性:
- 数据库是具有逻辑关系和确定意义的数据集合。逻辑上无关的数据集合不能称为数据库。
- 数据库是针对明确的应用目标而设计、建立和加载的。每个数据库都具有一组用户,并为这些用户的应用服务。
- 一个数据库表示了显示世界的某些方面,该现实的改变必须及时地反映到该数据库中来。
数据库管理系统
数据库管理系统是一个通用的软件系统,由一组计算机程序构成。数据库管理系统能够对数据库进行有效的管理,包括存储管理、安全性管理、完整性管理等。数据库管理系统 提供了一个软件环境,使用户方便快速地建立、维护、检索、存取和处理数据库中的信息。
数据库系统
数据库和数据库管理系统结合在一起就构成了数据库系统。有时人们把数据库系统广义地定义为“数据库 + 数据库管理系统 + 数据库管理员 + 应用程序 + 用户”。
数据库系统的特点与功能
数据库系统是在文件系统的基础上发展起来的。但是,数据库系统与文件系统具有本质上的区别。文件系统主要提供数据的物理存储和存取方法,数据的逻辑结构和输入输出 格式仍由程序员在程序中定义和管理。文件与应用程序紧密相关。每个文件都属于一个特定的应用程序。一个应用程序对应一个或几个文件。不同的应用程序独立地定义和处理 自己的文件。
文件系统具有如下缺点:
- 数据共享性差、冗余度大;
- 数据不一致性:由于相同数据的重复存储,单独管理,给数据的修改和维护带来了困难,容易造成数据不一致。
- 数据独立性差;
- 数据结构化程度低。
与文件系统相比,数据库系统具有很多优点。具体列举如下:
- 信息完整、功能通用:
数据库系统不仅存储数据库本身,同时也存储数据库的说明信息,这些说明信息称为元数据
。元数据存储在称为数据字典
的特殊文件中。元数据包括数据库中每个
文件的结构、每个数据项的存储格式和数据类型、数据的完整性约束等。数据字典主要由数据库管理系统软件使用,当然用户也可以使用。
在文件系统中,描述文件的元数据分散在不同的应用程序中。因此,每个应用程序只能存取特定的文件,无法使用它不了解其元数据的文件。反之,每个文件只能由一个应用 程序使用,不能被其他应用程序共享。数据库系统的通用性恰恰是由于抽象出了所有文件的元数据,统一存储,统一管理。
- 程序与数据独立
在文件系统中,文件的元数据嵌套在应用程序中。所以,文件结构的改变将引起所有存取这个文件的应用程序的改变。相比之下,数据库系统把所有文件的元数据与应用程序
隔离,统一存储和管理,从而克服了应用程序必须随文件结构的改变而改变的问题。我们程数据库系统的这个性质为程序与数据的独立性
。在数据库系统中,我们只
需要修改数据字典中的元数据,不需要修改任何应用程序(当然增加和删除后的数据,以前的应用程序可能无法使用这些数据)。而且,数据字典的修改是由数据库管理系统
自动完成的。
- 数据抽象
数据库系统提供了数据的抽象概念表示,使得用户不必了解数据库文件的存储结构、存储位置、存取方法等繁琐的细节就可以存取数据库。数据模型
是提供数据抽象
概念
表示的有力工具。
在文件系统中,每个文件的定义包括记录长度、每个数据项长度机器在记录中的初始位置等。在数据库系统中,用户一般都不想了解每个数据项有多长、存储记录的什么位置等 细节,只希望给出数据项名字就能存取争取的数据(而文件只实现了“按名存取”文件而不是记录和数据项)。为此,数据库系统为用户提供了只涉及文件名字和数据项名字 的数据的抽象概念表示,隐藏了文件的存储结构和存取方法等细节,用户只要使用这些名字就可以正确地存取数据。
在数据库系统中,每个数据库文件的存储结构、存取方法等详细存储在数据字典中。存取数据时,用户只需要引用数据的抽象概念表示,数据库管理系统负责从数据字典中提取 数据库文件的存储结构和存取方法等,把用户引用的抽象概念表示转换为物理表示,完成用户的存取要求。
- 支持数据的不同视图
一个数据库一般都要支持很多应用程序和用户。不同的应用程序和不同的用户对同一个数据库可能有不同的理解。我们称对同一个数据库的每一种理解为这个数据库的一个视图。 一个视图可以是一个数据库的子集合,也可以是多个数据库的子集按照某种方式构成的虚拟数据库(不是实际存储的数据库)。数据库系统提供了定义、维护和操纵视图的机制, 使得多个用户可以为他们的应用定义、维护和使用自己的视图。
- 控制数据冗余
数据库系统可以克服文件系统的数据冗余问题。在数据库设计阶段,我们只要充分考虑所有用户的数据管理需求,综合考虑所有用户的数据库视图,把它们集成一个逻辑模式, 每个逻辑数据项只存储一次,即可避免数据冗余。值得注意的是,为了提高数据库系统的性能,有时需要加以限制数据的冗余。比如,结构字段经常需要一起使用,则可以适当 对这些字段冗余(以存储换取时间),不过必须对数据冗余加以控制,防止数据的不一致性。
- 支持数据共享
- 限制非授权的存取:
为了保证数据库的安全,防止对数据库的非法存取,数据库系统具有一个安全与授权子系统。安全与授权子系统包括两方面的功能:第一。为数据库管理员提供建立用户账号和 密码,为用户规定存取数据库权限的工具;第二,进行安全性检查,当一个用户请求进入数据库系统时,安全与授权子系统黑对该用户和密码,禁止非法用户进入系统。
- 提供多种用户界面
- 表示数据之间的复杂联系:
数据库系统提供了两种鱼数据间联系相关的机制:一是数据间联系的定义机制,供用户定义数据之间的联系;二是通过数据间联系查询数据的机制,供用户通过数据间联系来 查询数据库中的数据。
- 完整性约束:
数据库应用对数据的语义一般都具有一定的限制。我们称这种限制为完整性约束
。数据项的数据类型是一种最简单的完整性约束,还有包含性约束、唯一性约束等。
数据库的完整性约束是在数据库设计阶段,由数据库设计者根据实际应用领域的数据语义推导出来的。数据库系统提供了两种机制来支持完整性约束:第一种机制是完整性定义 机制;第二种机制是完整性约束验证机制。我们通过完整性约束定义机制把数据库的完整性约束定义到数据库系统中。当用户执行一个数据更新操作时,完整性约束验证机制 验证这个更新操作是否能够保持完整性约束成立,如果不能,则拒绝该操作。
完整性约束并不能保证数据完全正确。这是因为数据库中满足完整性约束的数据不一定是正确的数据。
- 数据恢复:
系统恢复子系统可以采用两种方法保证系统故障恢复后数据库能够恢复到正确状态:一种方法是把数据库恢复到更新操作执行前的状态;另一种方法是使更新操作从故障发生 时的断点继续执行,保证该操作的更新结果全部写入数据库。
数据库系统的用户
大型数据库的设计、加载、维护可能涉及很多人。这些人员可以分为四类。没类人员都从不同的角度使用数据库系统。我们统称他们为数据库系统的用户。
- 数据库管理员
在任何一个组织机构中,如果很多人共享相同资源,则需要有一个特殊的人员来监督和管理这个共享资源。在数据库系统环境下,共享资源有两类:第一类是数据库;第二类
是数据库管理系统软件和相关软件。这些资源的监督管理由数据库管理员
完成。数据库管理员可以由一个人担任,也可以由一组人担任。数据库管理员负责数据库的
用户授权,并协调和监管他们对数据库和数据库管理系统软件的使用。数据库管理员也负责系统安全性保护和系统性能的监督和改善。
- 数据库设计者
数据库设计者负责数据库中数据的确定、数据库文件结构设计、存取方法的选择和数据库的最后定义。这些工作完成之后,所设计的数据库才能在数据库系统中实现。数据库 设计者首先需要与所有用户接触,讨论研究用户的需求,为每个用户建立起一个适应于他的应用的数据库视图。然后,数据库设计者合并这些视图,形成完整的数据库的定义。 最后形成的数据库必须能够支持所有用户的应用要求。最后,数据库设计者与数据库管理员合作,在数据库系统中建立数据库并加载数据。在很多情况下,数据库设计者由 数据库管理员担任。
- 最终用户
最终用户是数据库的主要用户,经常对数据库提出查询和更新等操作要求。数据库主要是为这类用户设计和存储的。最终用户可分为如下三类:
(1)偶然用户:这类用户不经常访问数据库。他们每次访问数据库时往往需要不同的数据库信息。他们通常使用数据库查询语言表示查询要求。他们一般都是一个企业或一个 组织机构的高中级管理人员。
(2)简单用户:数据库的多数最终用户都是简单用户。他们的主要工作是查询和更新数据库。他们一般都不直接使用数据库管理系统,而是通过应用程序员精心设计并具有 友好界面的应用程序存取数据库。如银行职员
(3)复杂用户:复杂用户包括工程师、科学家、经济学家、科学技术工作者等具有较高科学技术背景的人员。这类用户一般都比较熟悉数据库管理系统的各种服务机制,能够 直接通过数据库管理系统访问数据库。有些人甚至能够基于数据库管理系统编制自己的应用程序。
- 系统分析员和应用程序员:
系统分析员负责分析最终用户特别是简单最终用户的需求,给出适应这些用户需求的数据库事务的准确定义。
应用程序员负责把系统分析师提欧共的数据库事务的定义编制称为计算机软件,并进行编码、调试、维护。
系统分析员和应用程序员必须十分熟悉整个数据库管理系统,以完成他们的任务。
- 与数据库系统有关的其他人员:
除了数据库的设计者、管理者、使用者和应用程序设计者意外,还有如下三类与数据库系统有关的人员。
第一类人员是数据库管理系统的设计和实现人员。他们负责数据库管理系统软件本身的设计、编码、调试和维护,数据库管理员系统是一个时分复杂的计算机软件系统,包括 很多程序模块,如数据字典梳理模块、查询语言处理模块、查询优化模块、数据存取模块、事务处理模块、安全与完整性维护模块等。所有这些模块的设计和实现都是数据库 系统设计和实现人员的任务。
第二类人员是数据库系统工具开发者。数据库系统工具包括数据库设计软件包、性能监控软件包、自然语言查询处理软件包、图形界面软件包、应用程序辅助设计软件包等。 数据库系统工具开发者负责这些工具软件包的开发。很多数据库系统工具开发者都是独立于数据库系统开发公司的软件开发者。
第三类人员是操作员和系统维护人员。它们负责数据库系统赖以运行的硬件和软件环境的操作、维护和管理。
数据抽象(数据库系统的体系结构)
数据库系统的主要目的之一是为用户提供一个数据的抽象视图,隐藏数据的存储结构和存取方法等细节。
数据库的三种模式
数据库一般提供三种级别的数据抽象:
- 视图级抽象:它把现实世界抽象为数据库的外模式。
视图抽象把现实世界中的信息按照不同用户观点抽象为多个逻辑数据结构
。每个逻辑数据结构称为一个视图
,描述了每个用户所关心的数据。每个视图
抽象地描述了整个数据库的一个侧面。所有视图的集合形成了数据库的外模式
。数据库外模式是面向用户的数据库模式。数据库系统中数据定义语言的视图定义机构
提供了进行视图抽象的工具,可以用来定义视图的逻辑结构。
- 概念级抽象:它把数据库的外模式抽象为数据库的概念模式。
概念抽象
把数据库的外模式抽象为数据库的概念模式
。数据库的概念模式结合了外模式中所有视图,反映了所有数据库用户所关心的显示世界的抽象,形成了
数据库的整体逻辑结构。数据库系统中数据定义语言的逻辑数据库定义机构提供了进行概念抽象的工具,可以用来定义概念数据库模式的逻辑结构。
- 物理级抽象:它把数据库的概念模式抽象为数据库的内模式。
物理抽象
把数据库的概念模式进一步抽象称为数据库的内模式
。数据库的内模式抽象地描述了概念数据库如何在物理存储设备上存储。数据库的内模式包括两方面:
第一方面是存储策略的描述,包括数据和索引的存储方式、存储记录的描述、记录定位方法等;第二方面是存取路径的描述,包括索引的定义、HASH 结构定义等。数据库系统
中数据定义语言的物理数据库定义机构提供了物理抽象的工具,可以用来定义数据库的物理存储结构。
三种数据抽象和数据库模式的关系如下图:
数据独立性
数据库系统提供的三种数据抽象能力和三种数据库模式实现了两种数据间独立性。在介绍数据库系统的两种数据独立性之前,我们需要了解数据库三种模式之间映射的概念。 针对数据库的三种模式结构,数据库系统中包括两种映射:
- 外模式与概念模式之间的映射:该映射实现了外模式与概念模式的相互转换。
- 概念模式与内模式之间的映射:该映射实现了概念模式与内模式的相互转换。
数据库系统的两种映射实现了数据库系统的两种数据独立性:
- 物理数据独立性:
无理数据独立性由内模式与概念模式之间的映射实现。物理数据独立性
是指当数据库的内模式(即物理存储结构
)发生改变时,数据的逻辑结构不便。
物理数据独立性保证:当数据库的内模式发生改变时,用户编写的应用程序可以不便。但是,为了保证应用能够正确执行,我们需要修改内模式与概念模式之间的映射。
- 逻辑数据独立性:
逻辑数据独立性由概念模式与外模式之间的映射实现。逻辑数据独立性
是指当概念数据库模式发生改变时,数据库的外模式不便。逻辑数据独立性保证:当数据库的
概念模式发生改变时,建立在外模式上的应用程序不需要修改。当然,为了保证应用程序能够正确执行,我们需要修改概念模式与外模式之间的映射。
两种数据独立性的本质
是把数据定义从应用程序中分离出来,用用程序中的数据存取(即两种映射工作)由数据库管理系统完成,从而简化了编制应用程序的工作量,
减少了应用程序的维护和修改。
值得注意的是:
实际数据库系统的逻辑数据独立性不能保证直接建立在数据库概念模式上的应用程序的独立。当数据库概念模式改变时,这些应用程序仍然需要修改。从这种意义上讲。 数据库系统提供的逻辑数据独立性是不完备的。
视图的作用
视图最终是定义在基本表之上的,对视图的一切操作最终也要转换为对基本表的操作。而且对于非行列子集视图进行查询或更新时还可能出现问题。既然如此,为什么还要 定义视图呢?这是因为合理使用视图能够带来许多好处:
- 视图能够简化用户的操作
视图机制使用户可以将注意力集中在所关心的数据上。如果这些数据不是直接来自基本表,则可以通过定义视图,使数据库看起来结构简单、清晰、并且可以简化用户 的数据查询操作,如隐藏多表的连接操作。
- 视图使用户能以多种角度看待同一数据
视图机制能使不同的用户以不同的方式看待同一数据,当许多不同种类的用户共享同一个数据库时,这种灵活性是非常重要的。
- 视图对重构数据提供了一定程度的逻辑独立性
数据的物理独立性
是指用户的应用程序不依赖于数据库的物理结构。数据的逻辑独立性
是指当数据库重构时,如增加新的关系或对原有关系增加新的字段等,
用户的应用程序不会受影响。层次数据库和网状数据库一般能较好地支持数据的物理独立性,而对于逻辑独立性则不能完全地支持。
在关系数据库中,数据库的重构往往是不可避免的。重构数据库最常见的是将一个基本表“垂直”地分成多个基本表。例如:
这样尽管数据库的逻辑结构改变了(变为 SX 和 SY 两个表了),但应用程序不必修改,因为新建立的视图定义为用户原来的关系,使用户的外模式
保持不变,
用户的应用程序通过视图仍然能够查找数据。
当然,视图只能再一定程度上提供数据的逻辑独立性
,比如由于对视图的更新是有条件的,因此应用程序中修改数据的语句可能仍会因基本表结构的改变而改变。
- 视图能够对机密数据提供安全保护
有了视图机制,就可以在设计数据库应用系统时,对不同的用户定义不同的视图,使机密数据不出现在不应看到这些数据的用户视图上。这样视图机制就自动提供了对 机密数据的安全保护功能。例如 Student 表涉及全校 15 个院系的学生数据,可以在其上定义 15 个视图,每个视图只包含一个院系的学生数据,并只允许每个院系的 主任查询和修改自己系的学生视图。
- 适当的视图可以更清晰的表达查询
数据模型
数据抽象
是数据库系统的主要特点之一,具有很大的优越性。数据模型
是实现数据抽象的主要工具。数据模型决定了数据库系统的结构、数据定义语言和数据
操纵语言、数据库设计方法、数据库管理系统软件的设计与实现。
数据模型是一组描述数据库的概念。这些概念精确地描述数据、数据之间的联系、数据的语义和完整性约束。很多数据模型还包括一个操作集合。这些操作用来说明对数据库 的存取和更新。数据模型赢满足三方面要求:
- 真实地模拟现实世界;
- 容易为人们理解;
- 便于在计算机上实现。
目前已经存在很多数据模型。这些数据模型可分为四类:
- 基于对象数据模型;
- 基于记录的数据模型;
- 物理数据模型;
- 逻辑数据模型。
基于对象的数据模型
基于对象的数据模型用于在概念和视图抽象级别上描述数据。这些数据模型具有相当灵活的结构化能力,而且允许明确地定义完整性约束。目前已经出现了很多基于对象的 数据模型,其中比较知名的有:
- 实体-联系模型;
- 面向对象的数据模型;
- 二元数据模型;
- 语义数据模型;
- 函数数据模型等。
这里主要介绍实体-联系模型、扩展的实体联系模型和面向对象的数据模型。
实体-联系模型
实体-联系模型包括实体、属性、实体间联系等概念。
- 实体:对应于实现世界中刻区别的客观对象或抽象概念。
- 属性:是实体特征的抽象。
抽象地说,实体型是属性的集合。当一个实体型的所有属性的的值都确定以后,我们就得到了一个实例
。例如,在人的属性中,“姓名”和“生日”的值可以区别
不同的。这组特殊的属性称为实体型的键属性
。
实体间联系
对应于可观世界中各种对象或抽象概念之间的联系。实体-联系模型使用实体、属性、键属性、实体间联系这四个概念来抽象描述现实世界。
此外,实体-联系模型还具有表示完整性约束的能力
的能力,一个重要的完整性约束是实体间联系的基数(如 1:n,1:1等)。
实体-联系模型可以用来实现数据的视图抽象。
面向对象数据模型
与实体-联系模型类似,面向对象数据模型建立在对象集合的基础上。
- 面向对象数据模型的基本数据结构是
对象
; - 面向对象数据模型的主要概念是
对象类
。
对象类由一组变量和一组程序代码构成。变量
表示对象类的特征。一个对象类的程序代码定义了该对象变量上的操作,称为这个对象类的方法
。一个对象的变量
可以是另一个对象(合成
)。对象的嵌套层次数没有任何限制。当一个对象类的每个变量都赋以确定的值以后,我们就叨叨了这个对象的一个对象。把数据和方法组合
为一个对象的思想类似于程序设计语言中抽象数据类型的概念。
在面向对象的数据模型中,一个对象存取另一个对象的数据的唯一途径是调用被存取对象的某个方法。对象方法的调用通过在对象之间传送消息来实现。对象方法调用界面 是对外可见的,对象内部的变量和程序编码是封闭不可见的。面向对象数据模型实现了数据独立性。只要方法的接口没有变,应用程序就不需要修改。
在面向对象数据模型中,每个对象必须具有一个独立于该对象锁包含的值得唯一标识符。于是,具有相同值得对象可以标识为不同的对象。
面向对象的数据模型既能用来定义数据库的整体逻辑结构,也可以用来提供数据库系统实现的高级描述。
基于记录的数据模型
基于记录的数据模型可以用来定义数据库的概念模式和外模式。基于记录的数据模型把数据库定义为多种具有固定格式的记录型
。每个记录型由固定数量的域或属性
构成。每个域或属性
具有固定的长度。使用定长记录数据库可以简化数据库的物理级实现。基于记录的数据模型不包含直接表示程序代码的机构。这类数据模型具有
独立的语言。用户可以使用这种语言表示数据库查询和更新要求。具有代表性的基于记录的数据模型包括:
- 关系数据模型:
关系数据模型的核心是数学概念关系。一个关系可以视为一个表。每个表具有固定个数的列。每列具有一个名字,称为关系的属性。每一行数据称为一个元组
。
关系数据模型使用关系表示数据和数据之间的联系。
- 网络数据模型:
网络数据模型的核心是记录和系。记录表示数据。一个记录具有多个数据域。每个数据域表示一个数据项。数据之间的联系由系表示。系可以视为一个指针。
- 层次数据模型:
层次数据模型类似于网络数据模型。层次数据模型也使用记录和系表示数据和数据之间的联系。层次数据模型与网络数据模型的不同在于记录不能被组织成为任意的图, 必须组织成树的集合。
本节的详细内容请参考前面的“数据库类型(模型)”。
物理数据模型
物理数据模型是在逻辑数据模型的基础上,考虑各种具体的技术实现因素,进行数据库体系结构设计,真正实现数据在数据库中的存放。
物理数据模型的内容包括确定所有的表和列,定义外键用于确定表之间的关系,基于用户的需求可能进行发范式化等内容。在物理实现上的考虑, 可能会导致物理数据模型和逻辑数据模型有较大的不同。
物理数据模型的目标是指定如何用数据库模式来实现逻辑数据模型,以及真正的保存数据。比较知名的物理数据模型有:
- 一体化模型;
- 框架存储器模型。
数据库模式和实例
数据库一词包括了两方面的意义:
- 模式;
- 实例;
数据库模式
是一个数据库的基于特定数据模型的结构定义。类似于程序设计语言中的数据类型,是一个数据库的框架。
在任意一个特定的时刻,数据库中存储的数据称为一个数据库实例
。数据库实例与程序设计语言中的变量值的概念对应。
数据库模式是相对稳定的,很少变化。数据库实例是动态的,随数据库更新操作而变化。
数据库语言
每个数据库系统都为用户提供一个数据库语言。用户可以使用这个语言定义和操纵数据库。数据库语言包括两个子语言:
(1)数据定义子语言:
数据定义子语言
用来定义数据库模式,简记作 DDL。DDL 包括数据库模式定义
和数据库存储结构与存取方法
定义两方面。
数据定义子语言的处理程序也相应地分为两部分:数据库模式定义处理程序
、存储结构和存取方法定义处理程序
。
- 数据库模式定义处理程序
数据库模式定义处理程序接收用 DDL 表示的数据库模式定义,吧其变换为内部表示形式,存储到数据库系统中称为数据字典
的特殊文件中。
- 存储结构和存取方法定义处理程序
存储结构和存取方法定义处理程序接收用 DDL 表示的数据库的存储结构和存取方法定义,在存储设备上创建相关的数据库文件,建立起物理数据库。 数据定义子语言也包括数据库模式的删除与修改功能。
(2)数据操纵子语言:
数据操纵子语言
用来表示用户对数据库的操作请求。一般地,数据操纵语言能够表示如下的数据操作:
- 查询数据库中的信息;
- 向数据库插入新的信息;
- 从数据库删除信息;
- 修改数据库中的信息。
数据操纵语言分为两类:
- 过程性语言:
过程性语言
要求用户既说明需要数据库中的什么数据,也说明怎样搜索这些数据。
- 非过程性语言:
非过程性语言
只要求用户说明需要数据库中的什么数据,不需要说明怎样搜索这些数据。
非过程性语言容易学习和使用,但是,非过程性语言产生处理程序代码比过程性语言产生的代码效率低。这个问题可以通过各种查询优化技术来解决。
数据操纵语言的主要部分是查询数据库中的信息。我们称这部分为数据查询语言
。人们常把数据操纵语言称为查询语言。
在很多数据库中,这两个子语言(定义子语言、操纵子语言)被合并为一个语言。SQL 语言
是一个集数据定义和数据操纵子语言为一体的典型数据库语言。
目前关系数据库产品都提供 SQL 语言作为标准数据库语言。数据库语言与数据模型密切相关。基于不同数据模型的数据库系统的语言也不相同。
数据库管理系统的结构
数据库管理系统分为多个程序模块。每个模块实现数据库系统的一种功能。一般情况下,数据库系统建立在操作系统基础上。数据库的设计与实现必须考虑与操作系统接口的 问题。
详细结构
- 数据定义语言编译执行模块
该模块首先接收数据定义语言语句,进行语法检查等预处理,并调用安全性检查模块
进行安全性检查,然后处理数据定义语言语句。如果语句是建立数据库模式请求,
则形成元数据,写入数据字典;如果是撤销数据库模式请求,则从数据字典中删除相应数据库模式的元数据;如果是修改数据库模式请求,则修改数据字典的相应元数据。
- 查询预处理模块:
该模块接收用户的查询请求(存取数据库或更新数据库),进行语法检查,并调用安全性检查模块进行安全性检查,调用完整性约束模块
进行完整性约束验证。
- 查询优化处理模块:
该模块加工处理用户的查询请求,产生一个优化的查询执行计划。如果查询来自复杂用户,则根据查询执行计划的要求,调用数据操作模块
提供的各种数据操作算法,
完成用户查询的处理。如果查询来自应用程序,则把查询执行计划返回到数据操纵语言的预编译模块
.
- 数据操纵语言预编译模块
该模块调用查询预处理和查询优化处理模块,对应用程序中出现的查询进行优化,并调用宿主语言编译程序产生应用程序的目标代码。目标代码执行时,根据
查询执行计划的要求调用数据操作模块
提供的各种数据操作算法,完成用户查询的处理。
- 记录管理模块:
该模块调用并发控制模块、系统恢复模块、缓冲处理模块、记录存储模块、存取方法模块和数据存取模块等
,实现并发控制和系统恢复、I/O 缓冲处理、数据记录的存储
和存取等功能。记录管理模块还要管理各种存取方法,如 B-树索引、HASH 方法等。
简化结构
DBMS 的主要组成如下图:
最上方的查询
和更新
(还有模式更新)是 DBMS 的输入。查询和更新有两种生成方式:
- 通过通用的查询接口,用户输入相应语句进行操作;
- 通过应用程序的接口。
其中,对数据的插入、修改和删除等操作统称为更新
。
模式更新:
所谓数据库的模式
,就是指数据的逻辑结构(请参看“数据库的体系结构”)。模式更新命令一般只能由数据库管理员使用。
查询处理程序:
查询处理程序
不仅负责查询,也负责发出更新数据或模式的请求。查询处理程序的功能是:接受一个操作的请求后,找到一个最优的执行方式,然后向存储管理程序发出
命令,使其执行。存储管理程序的功能是从数据库中获得上层想要查询的数据,并根据上层的更新请求更新相应的信息。
存储管理程序:
在简单的数据库系统中,存储管理程序可能就是底层操作系统的文件系统;但有时为了提高效率,DBMS 往往直接控制磁盘存储器。存储管理程序包括两个部分:
- 文件管理程序:
文件管理程序
跟踪文件在磁盘上的位置,并负责取出一个或几个数据块,数据块中含有缓冲区管理程序所要求的文件。
- 缓冲区管理程序。
缓冲区管理程序
控制着主存的使用。它通过文件管理系统从磁盘取得数据块,并选择主存的一个页面来存放它。如果有另一个数据块想要使用这个页面,就把原来的数据
块写回磁盘。假如事务管理程序发出请求,缓冲区管理程序也会把数据块写回磁盘。
事务管理程序:
事务管理程序
负责系统的完整性。它必须保证同时运行的若干个数据库操作不互相冲突,保证系统在出现故障时不丢失数据。事务管理程序和查询处理程序互相配合,
因为它必须知道当前将要操作的数据,以免出现冲突。为了避免发生冲突,还可能需要延迟日志文件,记录等每一次数据的更新,这样即使系统出现故障,也能有效可靠地
进行恢复。
典型的 DBMS 允许用户吧一个或多个数据库操作(查询/更新)组成“事务”。可以认为,事务
是一组按顺序进行的操作单位。数据库系统常常允许多个事务并发地执行,
事务管理程序的任务就是保证这些事务全都能正确执行。那么这个“正确执行”的标准到底是什么呢?一般来说,满足下列四个特性,就可以任务事务正确执行了。这四个
特性是:
- 原子性:
整个事务要么都执行,要么都不执行,不能出现执行了一半的情况。
- 一致性:
数据库通常有个”一致状态“的概念,通俗地说,就是数据符合我们的所有期望何限定性条件。
- 隔离性:
当两个或更多的事务并发执行时,它们的作用效果必须相互独立,不能相互影响。也就是说,事务并发执行的效果应该和普通串行执行的效果完全一样。
- 持久性:
事务一经完成,即使系统出现故障,也要保证事务的结构不能丢失。
如何实现事务,才能使其具有上述四个特性呢?加锁、日志文件、事务提交等是常用的技术。下面对这几种技术作一简介。
- (1)加锁
造成事务之间的相互干扰的主要原因是多个事务同时读写数据库中的统一数据项。因此,多数事务管理程序能对事务要访问的数据项加锁。一个事务对数据项加锁后,其他的 事务就不能访问它了,直到该数据项解锁为止。
- 日志文件
事务管理程序记录了一个日志文件,包括每个事务的开始、每个事务所引起的数据库的更新和每个事务的结束。日志文件是记录在非易失性存储器上的,即使掉电,日志也能 完好保存。对所有的操作进行记录是保证持久性的重要手段。
- 事务提交
事务一般以“试验”的方式完成,就是说,在试验过程中,计算对数据库要做的更新,但并不真正地更新数据库本身。事务即将完成时,也就是事务提交的时候,更新的内容已经 复制到了日志文件中,然后再把更新的内容写入数据库。这样,即使在这两步之间系统出现故障,通过查看日志文件,就能知道系统恢复之后需要进行哪些数据库更新操作。 如果在这两步之前系统出现故障,我们可以重新执行该事务,确保不会发生错误。
客户程序/服务程序体系结构
现代的软件往往采用客户程序/服务程序体系结构。按照这种结构,在系统运行时,由一个进程(客户程序)发出请求,而由另一个进程(服务程序)去执行。从系统配置上, 服务程序通常安装在功能强大的服务器上,而客户程序就放在相对简单的 PC 机(客户机)上。数据库系统通常就是按这种体系结构,把上图各组成部分的分成一个服务进程 和一个或多个客户进程。
按照客户程序/服务程序的划分方式,DBMS 的核心部分都属于服务程序,而客户程序主要是与用户相互配合并将查询或其他命令传送给服务程序的查询接口。对于关系数据库 系统,通常用 SQL 语言表达从客户程序到服务程序的各种请求,然后由服务程序给出回答,用表即关系的形式传给客户程序。如果有很多用户同时使用数据库的话,服务 程序也可能会成为“瓶颈”。从这个角度考虑,也可使客户程序多分担一部分工作,以减轻服务程序的负担,从而使整个系统处于更好的运行状态。
数据库系统运行过程
下面通过介绍应用程序查询数据库数据的全过程让读者大致了解数据库系统运行的过程。
在应用程序运行时,数据库管理系统将开辟一个数据库系统缓冲区,用户数据的传输和格式的转换。数据库系统三成结构的描述放在数据字典(DD)中。
查询语句的具体执行过程如下:
(1)当计算机执行该语句时,启动数据库管理系统 DBMS。
(2)DBMS 首先对该语句进行语法检查,然后从数据字典 DD 中找出该应用程序对应的外模式(相当于关系数据库中的视图),检查是否存在锁要查询的关系,并进行权限检查, 即检查该操作是否在合法的授权范围内。如有问题,则返回出错信息。
(3)在决定执行该语句后,DBMS 从 DD 中调出相应的模式描述,并从外模式映像到模式,从而确定锁需要的逻辑数据。
(4)DBMS 从 DD 调出相应的内模式描述,并从模式映像到内模式,从而确定应读入的物理数据和具体的地址信息。
在查询过程中,DBMS 的查询处理程序将根据 DD 中的信息进行查询优化,并把查询命令转换成一串单记录(元组)的读出操作序列。随后 DBMS 执行读出操作序列。
(5)DBMS 在查看内模式决定从哪个文件、勇什么方式读取哪个物理记录之后,向操作系统发出从指定地址读取物理记录的命令,同时再系统缓冲区记下运行记录。当物理记录 全部读完时,转到(12)。
(6)OS 执行读出的命令,按指定地址从数据库中把记录读入 OS 的系统缓冲区,随后读入数据库(DB)的系统缓冲区。
(7)DBMS 根据查询命令和数据字典的内容把系统缓冲区中的记录转换成应用程序所要求的记录格式。
(8)DBMS 把数据记录从系统缓冲区传送到应用程序的用户工作区。
(9)DBMS 把执行成功与否的状态信息返回给应用程序。
(10)DBMS 把系统缓冲区中的运行记录计入运行日志,以备以后查询或发生意外时用于系统恢复。
(11)DBMS 在系统缓冲区中查找下一记录,若找到就转到(7),否则转到(5)。
(12)查询语句执行完毕,应用程序做后续处理。
从上述执行过程可以看出,在数据库系统中,数据库管理系统处于中心位置,而对数据库的操作则要以数据字典中的内容为依据。
关系数据库
关系数据库应用数学方法来处理数据库中的数据。关系数据模型是关系数据库系统的基础。关系数据库模型由三部分构成:
- 关系数据结构;
- 关系完整性);
- 关系运算(关系操作集合)。
关系数据库构成
前面已经提到了关系数据库由三部分构成。具体讲解如下。
关系数据结构
关系是关系数据模型的核心。关系是一个数学概念。当人们把关系的概念引入到数据库系统作为数据模型的数据结构时,这一概念既有所限定也有所扩充。
关系模型的数据结构非常简单,只包含单一的数据结构—-关系。在用户看来,关系模型中数据的逻辑结构是一张扁平的二维表。
关系模型的数据结构虽然简单却能够表达丰富的语义,描述出现实世界的实体以及实体间的各种联系。也就是说,在关系模现实世界的实体以及实体间的各种联系均用单一 的结构类型即关系来表示。
一般来说,笛卡尔积是没有实际语义的,只有它的某个子集才有实际含义。
关系
和关系模式
是关系数据库中密切相关但又有所不同的概念。关系模式
描述了关系的数据结构和语义约束,不是集合;而关系
是一个数据集合。
关系模式是相对稳定的;而关系是随时间变化的,是某一时刻现实世界状态的真是反映,是关系模式在某一时刻的“当前值”。我们称一个关系模式的任何一个“当前值”
为该关系模式的关系实例
。
若关系中的某一属性组的值能位移地标识一个元组,则程该属性为候选码
;若一个关系有多个候选码,则选定其中一个为主妈
;候选码的诸属性称为主属性
。
不包含在任何候选码中的属性称为非主属性
或非码属性
。在最简单的情况下,候选码只包含一个属性;在最极端的情况下,关系模式的所有属性是这个关系模式
的候选码,称为全码
。
关系可以有三种类型:
- 基本关系(又称为基本表或基表);基本表是实际存在的表,它是实际存储数据的逻辑表示。
- 查询表:其为查询结果对应的表。
- 视图表:视图表是由基本表或其他视图表导出的表,是虚表,不对应实际存储的数据。
基本表具有以下 6 条性质:
- 列是同质的,级每一列中的分量是同一类型的数据,来自同一个域。
- 不同的列克出资同一个域,称其中的每一列为一个属性,不同的属性要给予不同的属性名。
- 列的顺序无所谓,即列的次序可以任意交换的,因此很多数据库产品总是在最后插入列。
- 任意两个元组的候选码不能相同。
- 行的顺序无所谓,即行的次序可以任意交换(不过有些需要排序)。
- 分量必须取原子值(不过对象-关系型数据库有所改变),即每一个分量都必须是不可分的数据项。
关系模型要求关系必须是规范化的,即要求关系必须满足一定的规范条件。这些规范条件中最基本的一条就是,关系的每一个分量必须是一个不可分的数据项。规范化的关系
称为范式
(具体见后面章节)。
完整性约束规则
关系需要一个或一组属性作为键以标识关系中元组的唯一性。
关系模型的完整性约束如下:
- 实体完整性约束:
对于实体完整性规则说明如下:
(1)实体完整性规则是针对基本关系(基本表)而言。一个基本表通常对应现实世界的一个实体集。
(2)现实世界中的实体是可区分的,即它们具有某种唯一性标识。
(3)相应地,关系模型中以主码作为唯一标识。
(4)主码中的属性即主属性不能取空值。如果主属性取空值,就说明存在某个不可标识的实体,即存在不可区分的实体,这与第(2)点相矛盾,因此这个规则称为
实体完整性
- 关联(参照)完整性约束:
不仅两个或两个以上的关系间可以存在引用关系,同一关系内部属性间也可能存在引用关系。需要指出的是,外码并不一定要与相应的主码同名。不过,在实际应用当中, 为了便于识别,当外码与相应的主码属于不同关系时,往往给它们取相同的名字。
参照完整性规则就是定义外码与主码之间的引用规则。
- 用户定义的完整性
任何关系数据库都应该支持实体完整性和参照完整性。这是关系模型所必须的。除此之外,不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。
用户定义的完整性
就是针对某一具体关系数据库的约束条件。它反映某一具体应用所涉及的数据必须满足的语义要求(如某个非主属性也不能为空)。关系模型应
提供定义和检验这类完整性的机制,以便用统一的系统的方法处理它们,而不要由应用程序承担这一功能。
关系运算(操作)
早期的关系运算能力通常用代数方式或逻辑方式来表示,分别称为关系代数
和关系演算
。关系代数式用对关系的运算来表达查询要求的。关系演算
是用谓词来表达查询要求的。关系演算又可按谓词变元的基本对象是元组变量还是域变量分为元组关系演算
和域关系演算
。
关系数据语言的分类
关系代数、元组关系演算和域关系演算三种语言在表达能力上是完全等价的。而且它们均是抽象语言,这些抽象的语言与具体的 RDBMS 中实现的实际语言并不完全一样。 但它们能用作评估实际系统中查询语言能力的标准或基础。实际的查询语言除了提供关系代数或关系演算的功能外,还提供了许多附加功能,如关系赋值等
另外还有一种介于关系代数和关系演算之间的语言 SQL。SQL 不仅具有丰富的查询功能,而且具有数据定义和数据控制功能,是集查询、DDL、DML 和 DCL 于一体的关系 数据语言。它充分体现了关系数据语言的特点和优点,是关系数据库的标准语言。因此,关系数据语言可以分为三类:
这些关系数据语言的共同特点
是:语言具有完备的表达能力,是非过程化的集合操作语言,功能强,能够嵌入高级语言中使用。
关系代数
关系代数式一种抽象的查询语言,它用对关系的运算来表达查询。
任何一种运算都是将一定的运算符作用于一定的运算对象上,得到预期的运算结构。所以运算对象、运算符、运算结构是运算的三大要素。
关系代数的运算对象是关系,运算结构亦为关系。关系代数用到的运算符包括四类:
- 集合运算符;
- 专门的关系运算符;
- 算术比较符;
- 逻辑运算符。
关系代数的运算按运算符的不同可分为传统的集合运算
和专门的关系运算
两类。其中传统的集合运算将关系看成元组的集合,其运算时从关系的“水平”方向
即行的角度来进行。而专门的关系运算不仅涉及行而且涉及列。比较运算符和逻辑运算符是用来辅助专门的关系运算符进行操作的。
关系代数包括并、差、投影、笛卡尔积和选择五个基本操作,另外还有一些经常使用的附加操作,比如交、连接、商等操作。这些附加操作可以用五个基本操作表示。
传统的集合运算
传统的集合运算是二目运算,包括并、差、交、笛卡尔积四种运算。
专门的关系运算
专门的关系运算包括选择、投影、连接、除运算等。
选择:
选择运算实际上是从关系 R 中选取使逻辑表达式 F 为真的元组。这是从汗的角度进行的运算。
投影:
关系 R 上的投影是从 R 中选择出若干属性列组成新的关系。可见,投影操作时从列的角度进行的运算。
连接:
一般的连接操作时从行的角度进行运算。但自然连接还需要取消重复咧,所以是同时从行和列的角度进行运算。
除操作(商运算):
除操作时同时从行和列角度进行运算。
元组关系演算
关系演算是以数理逻辑中的谓词演算为基础的。按谓词变元的不同,关系演算可分为元组关系演算和域关系演算。
域关系演算
关系运算的安全性
由于计算机不能处理无限关系,也不能进行无穷验证,所以我们不希望关系运算导致无限关系
和无穷验证
。直观地说,如果一个关系运算不产生无限关系和无穷验证,则
这个关系运算系统是安全
的。
从关系代数操作的定义可以看出,任何一个有限关系上的关系代数操作结构不会导致无限关系和无穷验证。所以,关系代数系统是安全的。然而,元组关系演算系统和 域关系演算系统可能产生无限关系和无穷验证。
关系运算的等价性
如果两个表达式锁表达的关系相同,我们称这两个表达式为等价表达式
。我们使用如下方法证明关系代数、元组关系演算、域关系演算的等价性:
- 证明每个关系代数表达式都有一个等价的安全元组演算表达式与之对应;
- 证明每个安全元组演算表达式都有一个等价的安全域关系演算表达式与之对应;
- 证明每个安全的域关系演算表达式都有一个等价的关系代数表达式与之对应。
关系数据库查询语言
前面已经讲述了关系代数、元组关系演算和域关系演算的相关知识,而且证明了这三种关系运算系统在表达能力上是等价的。E.F.Codd 提出了考察关系数据库查询语言的 标准,即与元组关系演算的表达能力等价的查询语言是完备的。
由于关系代数、元组关系演算和域关系演算的表达能力相同,所以绝大多数关系数据库查询语言都是以这三种关系运算系统为基础建立起来的。如:
- IBM 英国科学中设计的 ISBL 是一种纯关系代数查询语言;
- INGRES 关系数据库系统的 QUEL 语言是一种近似于元组关系演算的查询语言;
- IBM 公司研制的 QBE 语言是一种域关系演算语言;
- 目前使用最广泛的 SQL 语言是一种既由关系代数特点又有关系演算特点的查询语言。
数据库语言一般都允许两种使用方式:
- 一种方式是交互使用:
即,用户通过计算机终端设备直接向数据库系统输入数据库语言语句,请求数据库系统的服务;
- 嵌入方式:
把数据库语言嵌入到某个程序设计语言中,作为这个程序设计的子程序使用。这个程序设计语言称为宿主语言
。应用程序员可以在宿主语言程序的任何地方使用
数据库语言语句,向数据库系统提出操作要求。
- 接口式:
在用编程语言编写代码时,引用一个或多个数据库连接通用的接口库,使程序能通过对这些接口库函数或对象的调用来传入 SQL 语句,并间接执行 SQL 语句,这种方式 被称为接口式,也称为 API 式。提供的接口库有 ODBC、JDBC、OCI 等。
关系数据库标准语言 SQL
和许多流行的编程语言(例如,C++、Java、Visual Basic 和 C#)不同,SQL 用于处理数据集,而且是非过程语言。也就是说,在其他编程语言中被认为理所当然的特性, 如流控制语句、循环语句等,在 SQL 中完全没有,
非过程化语言
在本质上提交一个命令,具有询问和查询类型特性。 SQL 是由单个命令组成的非过程化语言。其中数据库自身做许多工作以决定如何获得信息。另一个
方面,过程化语言包含命令块
。这些命令块是有区别的步骤序列,通常每个后继的步骤都依赖于该序列中的前一个命令的结构。
SQL 概述
SQL 实现了数据存储、数据检索及数据操作功能,它与数据库管理系统(DBMS)紧紧地地联系在一起,既不能存在于 DBMS 之外,也不能在 DBMS 外执行。我们要做的就是 将一个查询提交到 DBMS,然后再某些客户端程序中得到结构,这些结构可以是从数据库得到的真实数据,也可以是一项任务的状态结构(如,插入或删除记录)。
和编程风格的变量操作不同,插入数据、更新数据和检索数据都是基于集的过程。SQL 语句操作于数据集,虽然在 SQL 程序员看来,完成一项操作可能要花费很长的时间, 但这些操作却是不包含任何留控制。当然,在某些过程语言(通常是 C 语言)中会实现执行 SQL 查询的引擎。大多数情况下,不管它多短多简单或者多长多复杂,一个 SQL 程序就是作为一个整体来执行一条或多条语句。
SQL 的特点
为了解决 SQL 程序不足所引发的问题,数据库供应商提供了许多自己的 SQL 函数和程序扩展插件。SQL 是用于对存放在数据库中的数据进行组织、管理和检索的工具,是 关系数据库的高级语言。具有以下显著特点:
综合统一:
数据库系统的主要功能是通过数据库支持的数据语言来实现的。
非关系数据库
(层次模型、网状模型)的数据语言一般都分为:
- 模式数据定义语言(模式 DDL);
- 外模式数据定义语言(外模式 DDL 或子模式 DDL);
- 数据存储有关的描述语言(DSDL);
- 数据操纵语言(DML)。
它们分别用于定义模式、外模式、内模式和进行数据存取与处置。当用户数据库投入运行后,如果需要修改模式,必须停止现有数据库的运行,转储数据,修改模式并编译 后再重装数据库,十分麻烦。
*SQL 则集数据定义语言 DDL、数据操纵语言 DML、数据控制语言 DCL 的功能于一体,语言风格统一,可以独立完成数据库生命周期中的全部活动,包括:
- 定义关系模式,插入数据,建立数据库;
- 对数据库中的数据进行查询和更新;
- 数据库重构和维护;
- 数据库安全性、完整性控制等一系列操作。
这就为数据库应用系统的开发提供了良好的环境。特别是用户在数据库系统投入运行后,还可根据需要随时地逐步地修改模式,并不影响数据库的运行,从而是系统具有 良好可扩展性。
另外,*在关系模型中实体和实体间的联系均用关系表示,这种数据结构的单一性带来了数据操作符的统一性,查找、插入、删除、更新等每一种操作都只需一种操作符, 从而克服了非关系系统由于信息表示方式的多样性带来的操作复杂性。
SQL 语言包含如下三种自语言完成关系数据库需要的几乎所有的操作:
- 数据定义语言(DDL);
- 数据操作语言(DML);
- 数据查询语言(DQL)。
DDL
用来定义数据库结构,包括创建和删除表、定义视图、索引以及约束条件等等。DML
用来实现数据的修改,而 DQL
用来检索数据。
由于 SQL 是使用关系模型来创建数据库的标准语言,这就使得关系数据库具有很好的可移植性,可以移植到任何不同的环境。用户掌握 SQL 后,经过很小的调整,就可以 使用任何关系数据库。
可见,DQL 集数据查询、数据操作、数据定义和数据控制功能于一身,充分体现了关系数据语言的优越性,是一种功能强大、通用性号又简单易学的语言。
高度非过程化
非关系数据模型
的数据操纵语言是“面向过程”的语言,用“过程化”语言完成某项请求,必须指定存取路径。而用 DQL
进行数据操作,只要提出“做什么”,而无须指明
“怎么做”,因此无需了解存取路径。存取路径的选择以及 DQL 的操作过程由系统自动完成。这不但大大减轻了用户负担,而且有利于提高数据独立性。
面向集合的操作方式
非关系数据模型
采用的是面向记录的操作方式,操作对象是一条记录。例如查询所有平均成绩在 80 分以上的学生姓名,用户必须一条一条地把满足条件的学生记录
找出来(通常要说明具体处理过程,即按照哪条路径,如何循环等)。而SQL
采用集合操作方式,不仅操作对象、查找结构可以是元组的集合,而且一次插入、删除、
更新操作的对象也可以是元祖的集合。
以同一种语法结构提供多种使用方式
SQL 既是独立的语言,有时嵌入式语言。
作为独立的语言,它能够独立当用于联机交互的使用方式,用户可以在终端键盘上直接键入 SQL 命令对数据库进行操作;作为嵌入式语言,SQL 语句能够嵌入到高级语言 程序中,供程序员设计程序时使用。而在两种不同的使用方式下,SQL 的语法结构基本上是一致的。这种以统一的语法结构提供多种不同使用方式的做法,提供了吉大的 灵活性与方便性。
语言简洁,易学易用
SQL 功能极强,但由于涉及巧妙,语言时分简洁,完成核心功能只用了 9 个动词,如下表所示:
DQL 基本概念
支持 SQL 的 RDBMS 同样支持关系数据库三级模式结构,如下图:
其中外模式
对应于视图和部分基本表,模式
对应于基本表,内模式
对应于存储文件。用户可以用 SQL 对基本表和视图进行查询或其他操作,基本表
和视图一样,都是关系。
- 基本表:
基本表是本身独立存在的表,在 SQL 中一个关系就对应一个基本表。一个(或多个)基本表对应一个存储文件,一个表可以带若干索引,索引也存放在存储文件中。
- 存储文件:
存储文件的逻辑结构组成了关系数据库的内模式。存储文件的物理结构是任意的,对用户是透明的。
- 视图:
视图是从一个或几个基本表导出的表。它本身不独立存储在数据库中,即数据库中只存放视图的定义而不存放视图对应的数据。这些数据仍存放在导出视图的基本表中,
因此视图是一个虚表
。视图在概念上与基本表等同,用户可以在视图上再定义视图。
SQL 各供应商间差异
虽然各 SQL 语句涉及到的基本概念和基本功能是基本相同的,但各个 RDBMS 产品在实现标准 SQL 时各有差别,与 SQL 标准的符合程度也不相同,一般在 85% 以上。 因此,具体使用某个 RDBMS 产品时,还应参阅系统提供的有关手册。
各个 RDBMS 产品各有差别是因为,SQL 的以下内容是留给供应商实现的:
- 语义和语法差异;
- 为处理技术打开一个数据库:
ODBC、OLEDB、JDBC 和其他接口并不是 SQL 标准的一部分,尽管 SQL 标准已将 CLI(呼叫级接口)定义为 ISO/IEC 9075-3:2003/Cor1:2005 的一部分。
- 动态和嵌入的 SQL 实现会因提供商的不同而有所差异;
- 排序顺序:
已排序的查询结果是如何呈现呢?这依赖于是否使用了 ASCII 或 EBCDIC 字符。虽然 UNICODE 标准解决了这一问题,仍然存在大量的旧有数据和应用程序。
- 不同的数据类型扩展:自定义结构、混合数据类型、对象等;
- 数据库目录表中的差异:
由于这仅在完全一致性级别标准下回提到,在核心一致性下工作的供应商没有理由放弃自己的专有结构。
数据类型
在关系模型中一个很重要的概念是域。每一个属性来自一个域,它的取值必须是域中的值。在 SQL 中域的概念用数据类型来实现。定义表的各个属性时需要指明其数据类型 及长度。SQL 提供了一些主要数据类型,要注意的是,不同的 RDBMS 中支持的数据类型不完全相同(具体参考相应产品说明)。
一个属性选用哪种数据类型要根据实际情况来决定,一般要从两个方面考虑,一是取值范围,二是要做哪些运算。例如,对于年龄属性,可以采用 CHAR(3) 作为数据类型, 但考虑到要在年龄上做算术运算(如求平均年龄),所以要采用整数作为数据类型,因为 CHAR(n) 数据类型不能进行算术运算。整数又有长整数和短整数两种,因为一个人 的年龄在百岁左右,所以选用短整数作为年龄的数据类型。
数据定义
关系数据库系统支持三级模式结构:模式、外模式和内模式。这三种模式中的基本对象有表、视图和索引。因此 SQL 的数据定义功能包括模式定义、表定义、视图和索引 的定义,如下表所示:
SQL 通常不提供修改模式定义、修改视图定义和修改索引定义的操作。用户如果想修改这些对象,只能先将它们删除掉,然后再重建。
数据定义语句
(DDL)用来创建、删除或者更改一个数据模式对象的记过,是对数据库重要元数据(Meta Data)的管理。这里的元数据
指的是前述数据意义的数据。
DDL 语言就是通过对元数据的操作来管理数据库模式的各种结构的。在每一条 DDL 语句执行前后,系统都将隐式提交当前事务。在使用 DML 子语句修饰 DDL 语句的执行
语句中,通常系统会自动提交 DML 语句的内容。
创建数据库
创建数据库用 CREATE DATABASE 命令,创建数据库由很多个参数可以自定义也可以使用默认值。在创建数据库前需要确定数据库的存储空间和数据库的日志模式等。不同的 DBMS 系统对数据库概念是不一致的。
具体详细的用法其参考相应产品的帮助手册。
模式的定义与删除
定义模式
在 SQL 中,模式定义语句如下:
CREATE SCHEMA <模式名> AUTHORIZATION <用户名>
如果没有指定 <模式名>,那么<模式名> 隐含为 <用户名>。用户名>模式名>模式名>
要创建模式,调用该命令的用户必须拥有 DBA 权限,或者获得了 DBA 授予的 CREATE SCHEMA 的权限。
定义模式实际上定义了一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象,例如基本表、视图、索引等(创建语句见前面表格“SQL 的数据定义语句”)。 目前在 CREATE SCHEMA 中可以接受 CREATE TABLE,CREATE VIEW 和 GRANT 子句。
删除模式
在 SQL 中,删除模式语句如下:
DROP SCHEMA <模式名> <CASCADE | RESTRICT>
其中 CASCADE 和 RESTRICT 两者必选其一。
- CASCADE
选择了 CASCADE(级联),表示在删除模式的同时把该模式中所有的数据库对象全部一起删除。
- RESTRICT
选择了 RESTRICT(限制),表示如果该模式中已经定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。只有当模式中没有任何下属的对象时才能执行 DROP SCHEMA 语句。
模式与表
每一个基本表都属于某一个模式,一个模式包含多个基本表。当定义基本表同时定义它所属的模式一般可以有三种方法:
- 在表名中明显地给出模式名,例如
- 在创建模式语句中同时创建表,如[例3]所示。
- 设置所属的模式,这样在创建表时表名中不必给出模式名。
当用户创建基本表(吉他数据库对象也一样)时候若没有指定模式,系统根据搜索路径来确定该对象所属的模式。搜索路径
包含一组模式列表,RDBMS 会使用模式
列表中第一个存在的模式作为数据库对象模式名。若搜索路径中模式名都不存在,系统将给出错误。
基本表的定义、删除与修改
定义基本表
创建了一个模式,就建立了一个数据库的命名空间,一个框架。在这个空间中首先要定义的是该模式包含的数据库基本表。SQL 语言使用 CREATE TABLE 语句定义基本表, 其基本格式如下:
CREATE TABLE <表名>(<列名> <数据类型> [列级完整性约束条件]
[,<列名> <数据类型> [列级完整性约束条件]
...
[,表级完整性约束条件]);
建表的同时通常还可以定义与该表有关的完整性约束条件,这些完整性约束条件被存入系统的数据字典中,当用户操作表中数据时由 RDBMS 自动检查该操作是否违背这些 完整性约束条件。如果完整性约束条件涉及到该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级。
修改基本表
随着应用环境和应用需求的变化,有时需要修改已建立好的基本表,DQL 语言用 ALTER TABLE
语句修改基本表,其一般格式为:
ALTER TABLE <表名>
[ ADD <新列名> <数据类型> [ 完整性约束 ]]
[ DROP <完整性约束名> ]
[ ALTER COLUMN <列名> <数据类型> ];
其中 <表名> 是要修改的基本表,ADD 子句用于增加新列和新的完整性约束条件,DROP 子句用于删除指定的完整性约束条件,ALTER COLUMN 子句用于修改原有的列定义, 包括修改列名和数据类型。表名>
删除基本表
当某个基本表不再需要时,可以使用 DROP TABLE
语句删除它。其一般格式为:
DROP TABLE <表名> [RESTRICT | CASCADE];
- RESTRICT
缺省自动选择 RESTRICT。选择 RESTRICT 则该表的删除是有限制条件的。欲删除的基本表不能被其他表的约束所引用(如 CHECK,FOREIGN KEY 等约束), 不能有视图,不能有触发器,不能有存储过程或函数等。如果存在这些依赖该表的对象,则此表不能删除。
- CASCADE
选择 CASCADE 则该表的删除没有限制条件。在删除基本表的同时,相关的依赖对象,例如视图,都将被一起删除。
同样,对于其他的 SQL 语句,不同的数据库产品在处理策略上会与标准有所差别。
索引的建立与删除
建立索引是加快查询速度的有效手段。用户可以根据应用环境的需要,在基本表建立一个或多个索引,以提供多种存取路径,加快查找速度。
一般来说,建立与删除索引由数据库管理员 DBA 或表的属主(owner)负责完成。系统在存取数据时会自动选择合适的索引作为存取路径,用户不必也不能显式地选择索引。
建立索引
在 SQL 语言中,建立索引使用 CREATE INDEX 语句,其一般格式为:
CREATE [ UNIQUE ][ CLUSTER ] INDEX <索引名>
ON <表名>( <列名> [ <次序> ][,<列名> [ <次序> ]]...);
其中,<表名> 是要建索引的基本表的名字。索引可以建立在该表的一列或多列上,各列名之间用逗号分隔。每个 <列名> 后面还可以用 <次序> 指定表索引值得排列次序, 可选 ASC(升序)或 DESC(降序),缺省值为 ASC。次序>列名>表名>
UNIQUE
表明此索引的每一个索引值只对应唯一的数据记录。
CLUSTER
表示要建立的索引是聚簇索引。所谓聚簇索引
是指索引项的顺序与表中记录的物理顺序一致的索引组织。
用户可以在最经常查询的列上建立聚簇索引以提高查询效率。显然在一个基本表上最多只能建立一个聚簇索引。建立聚簇索引后,更新该索引列上的数据时,往往导致表中 记录的物理顺序变更,代价较大,因此对于经常更新的列不宜建立聚簇索引。
用户使用 CREATE INDEX 语句定义索引时,可以定义索引是位移索引、非唯一索引或聚簇索引。至于某一个索引是采用 B+ 树,还是 HASH 索引则由具体的 RDBMS 来决定。
删除索引
索引一经建立,就由系统使用和维护它,不需用户干预。建立索引是为了减少查询操作的时间,但如果数据增删改频繁,系统会花费许多时间来维护索引,从而降低查询 效率。这是,可以删除一些不必要的索引。
在 SQL 中,删除索引使用 DROP INDEX
语句,其一般格式为:
DROP INDEX <索引名>;
删除索引时,系统会同时从数据字典中删去有关该索引的描述。
在 RDBMS 中索引一般采用 B+ 树、HASH 索引来实现。B+ 树索引具有动态平衡的优点。HASH 索引具有查找速度快的特点。索引是关系数据库的内部实现技术,属于内模式 的范畴。
视图定义、删除、更新
定义视图
定义视图用 CREATE VIEW 语句。视图是对表定义的查询,自己不存储数据,是逻辑上的表,它可以组合多个表的数据,供不同应用需要。例如:
删除视图
删除视图用 DROP VIEW 命令。对视图的删除并不影响实际储存的数据。例如:DROP VIEW clerk;
更新视图
更新视图有 3 种意义上的更新:
- 将视图定义的查询语句进行修改,使用
REPLACE VIEW
命令; - 使用 ALTER VIEW 命令重新编译视图或者修改视图的各种约束;
- 对视图中的数据进行更新,由于视图可以定义在多个关系的基础上,对于视图的选取属性不一定是关系的全部属性,所以对于数据插入操作,没有选取出的关系属性 将出现空值,这有时会出现许多异常,所以视图中数据的更新当且仅当定义在单个关系上才被允许。
简单(单表)查询
数据操作语句(DML)用来改变表中的数据或者查询数据表中的数据,但是不该表表或其他对象的结果。而数据库查询是数据库的核心操作。 SQL 提供了 SELECT 语句进行数据库的查询,该语句具有灵活的使用方式和丰富的功能。其一般格式为:
SELECT [ALL | DISTINCT] <目标列表达式> [,<目标列表达式>]...
FROM <表名或视图名> [,<表名或视图名> ]...
[ WHERE <条件表达式> ]
[ GROUP BY <列名 1> [ HAVING <条件表达式> ]]
[ ORDER BY <列名 2> [ ASC | DESC]];
整个 SELECT 语句的含义是,根据 WHERE 子句的条件表达式,从 FROM 子句指定的基本表或视图中找出满足条件的元组,再按 SELECT 子句中的目标列表达式,选出元组 中的属性值形成结果表。
- GROUP BY
如果有 GROUP BY 子句,则将结果按 <列名 1> 的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数
。
- HAVING
如果 GROUP BY 子句带 HAVING 短语,则只有满足指定条件的组才予以输出。
- ORDER BY
如果有 ORDER BY 子句,则结果表还要按 <列名 2> 的值得升序或降序排序。
SELECT 语句既可以完成简单的单表查询,也可以完成复杂的连接查询和嵌套查询。
单表查询—选择列
单表查询是指仅涉及一个表的查询。
查询指定列
很多情况下,用户只对表中的一部分属性列表感兴趣,这时可以通过在 SELECT 子句中的 <目标列表达式>
中指定要查询的属性列。
查询全部咧
将表中的所有属性列都选出来,可以有两种方法。一种方法就是在 SELECT 关键字后面列出所有列名。如果列的显示顺序与其在基表中的顺序相同,也可以简单地将
<目标列表达式>
指定为 *
。
查询经过计算的值
SELECT 子句的 <目标列表达式>
不仅可以是表中的属性列,也可以是表达式。
<目标列表达式>
不仅可以是算术表达式,还可以是字符串常量、函数等。
用户可以通过指定别名
来改变查询结果的列标题,这对于含算术表达式、常量、函数名的目标列表达式尤为有用。例如对于上例,可以定义如下列别名:
单表查询—选择元组
消除取值重复的行
两个本来并不完全相同的元组,投影到指定的某些列上后,可能变成相同的行了,可以用 DISTINCT 取消它们。
查询满足条件的元组
查询满足指定条件的元组可以通过 WHERE 子句实现。WHERE 子句常用的常用条件如下表所示:
- 比较大小
用于比较的运算符一般包括:
=(等于),>,<,>=,<=,!=或<>(不等于),!>(不大于),!<
RDBMS 执行该查询的一种可能过程是:对 Student 表进行全表扫描,取出一个元组,检查该元组在 Sdept 列的值是否等于 ‘CS’。如果相等,则取出 Sname 列的值形成一个 新的元组输出,否则跳过该元组,取下一个元组。
如果全校有数万个学生,计算机系的学生人数是全校学生的 5% 左右,可以在 Student 表的 Sdept 列上建立索引,系统会利用该索引找出 Sdept = ‘CS’ 的元组,从中 取出 Sname 列值形成结果关系。这就避免了对 Student 表的全表扫描,加快查询速度。注意:如果学生较少,索引查找不一定能提高查询效率,系统仍会使用全表扫描。 这由查询优化器按照某些规则或估计执行代价来做出选择。
- 确定范围
谓词 BETWEEN…AND… 和 NOT BETWEEN…AND…可以用来查找属性在(或不在)指定范围内的元组。
- 确定集合
谓词 IN 可以用来查找属性值属于指定集合的元组。
- 字符匹配
谓词 LIKE 可以用来进行字符串的匹配。其一般语法格式如下:
[NOT]LIKE '<匹配串>'[ESCAPE' <换码字符>']
其含义是查找指定的属性列值与 <匹配串>
相匹配的元组。<匹配串>
可以是一个完整的字符串,也可以含有通配符 %
和 _
。其中:
- %
百分号代表任意长度(长度可以为 0)的字符串。
- _
下划线代表单个字符。
涉及空值得查询
多重条件查询
逻辑运算符 AND 和 OR 可用来联结多个查询条件。AND 优先级高于 OR,但用户可以用括号改变优先级。
ORDER BY 子句
用户可以用 ORDER BY
子句对查询结果按照一个或多个属性咧的升序(ASC)或降序(DESC)排列,缺省值为升序。
对于空值,若按升序排,含空值的元组将最后显示;若按降序拍,空值的元组将最先显示。
聚集函数
为了进一步方便用户,增强检索功能,SQL 提供了许多聚集函数,主要有:
如果指定 DISTINCT 短语,则表示在计算时要取消指定列中的重复值。如果不指定 DISTINCT 短语或指定 ALL 短语(ALL 为缺省值),则表示不取消重复值。
GROUP BY 子句
GROUP BY 子句将查询结果按某一列或多列的值分组,值相等的为一组。
对查询结果分组的目的是为了细化聚集函数的作用对象。如果未对查询结果分组,聚集函数将作用于整个查询结果。分组后聚集函数将作用于没一个组,即每一组都有一个 函数值。
如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足执行条件的组,则可以使用 HAVING
短语指定筛选条件。
WHERE
子句与 HAVING
短语的区别在于作用对象不同。WHERE 子句作用于基本表或视图,从中选择满足条件的元组。HAVING 短语作用于组,从中选择满足
条件的组。
视图查询
视图定义后,用户就可以像对基本表一样对视图进行查询了。
RDBMS 执行对视图的查询时,首先进行有效性查询。检查查询中设计的表、视图等是否存在。如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的
查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。这一转换过程称为视图消解
。
目前多数关系数据库系统对行列子集视图的查询均能进行正确转换。但对非行列式子集视图的查询(如例 11)就不一定了,因策这些查询应该直接对基本表进行。
连接查询
若一个查询同时涉及两个以上的表,则称之为连接查询。连接查询是关系数据库中最主要的查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、 外连接查询和符合条件连接查询等。
关系代数的强大表达能力来自于它能够通过并、交、差、自然连接、笛卡尔积等运算将两个或两个以上的关系连接起来,从而完成复杂的查询任务。并、交、差在 SQL 中 各自有相应的关键字来表示,至于连接和笛卡尔积,不需要有额外的关键字,仅仅使用普遍的 SELECT-FROM-WHERE 语句,就可以方便的表示。
等值与非等值连接查询
连接查询的 WHERE
子句中用来连接两个表的条件称为连接条件
或连接谓词
,其一般格式为:
[ <表名 1>.] <列名 1> <比较运算符> [ <表名 2>. ]<列名 2>
其中比较运算符主要有:=、>、<、>=、<=、!=
等。
此外连接谓词还可以使用下面形式:
[ <表名 1>. ]<列名 1> BETWEEN [<表名 2>.]<列名 2> AND [<表名 2>.]<列名 3>
当连接运算符为 =
时,称为等值连接
。使用其他运算符称为非等值连接
。连接谓词中的列名称为连接字段
。连接条件中的各字段类型必须是
可比的(如数据类型),但名字不必相同。
本例中,SELECT 子句与 WHERE 子句中的属性名前都加上了表名前缀,者是为了避免混淆。如果属性名在参加连接的各表中是唯一的,则可以省略表名前缀。
自然连接查询
自然连接(Natural join)是一种特殊的等值连接,它要求两个关系中进行比较的分量必须是相同的属性组,并且在结果中把重复的属性列去掉。 而等值连接并不去掉重复的属性列。
上节例子改造如下,就变成了自然连接:
自身连接查询
连接操作不仅可以在两个表之间进行,也可以是一个表与其自己进行连接,称为表的自身连接
。
内连接查询
全外连接查询
外联接。外联接可以是左向外联接、右向外联接或完整外部联接。在 FROM子句中指定外联接时,可以由下列几组关键字中的一组指定:
- 1)LEFT JOIN或LEFT OUTER JOIN
左向外联接的结果集包括 LEFT OUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行, 则在相关联的结果集行中右表的所有选择列表列均为空值。
- 2)RIGHT JOIN 或 RIGHT OUTER JOIN
右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
- 3)FULL JOIN 或 FULL OUTER JOIN
完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行, 则整个结果集行包含基表的数据值。
左外连接查询
在通常的连接操作中,只有满足连接条件的元组才能作为结果输出。如“等值与非等值连接查询”一节中的图中结果表中没有 200215123 和 200215125 两个学生的信息, 原因在于他们没有选课,在 SC 表中没有响应的元组,造成 Student 中这些元组在连接时被舍弃了。
有时想以 Student 表为主体列出每个学生的基本情况及其选课情况。若某个学生没有选课,仍把舍弃的 Student 元组保存在结果关系中,而在 SC 表的属性上填空值(Null),
这时就需要使用外连接
。
右连接查询
概念:恰与左连接相反,返回右表中的所有行,如果右表中行在左表中没有匹配行,则结果中左表中的列返回空值。
select * from T_student s right join T_class c on s.classId = c.classId
交叉连接(CROSS JOIN)
概念:不带 WHERE 条件子句,它将会返回被连接的两个表的笛卡尔积
,返回结果的行数等于两个表行数的乘积
(例如:T_student和T_class,返回 4*4=16 条记录),如果带 where,返回或显示的是匹配的行数。
- 不带 where:
select *from T_student cross join T_class ‘等于 select *from T_student, T_class
- 带 where:
有where子句,往往会先生成两个表行数乘积的数据表,然后才根据where条件从中选择
select * from T_student s cross join T_class c where s.classId = c.classId
(注:cross join后加条件只能用where,不能用on)
查询结果跟等值连接的查询结果是一样。
Union 查询形成并集
要是用 Union 来连接结果集(也可以由于一个表),需要满足 4 个限定条件:
- 子结果集要具有相同的结构。
- 字结果集的列数必须相同。
- 子结果集对应的数据类型必须可以兼容。
- 每个子结果集不能包含 order by 和 compute 子句。
语法格式为:
select_statement union [all] select_statement
all代表最终的结果集中将包含所有的行,而不能删除重复行。实例如下:
SELECT Name FROM Person_1 UNION SELECT Name FROM Person_2
注意到重复记录,孙权与周瑜仅仅显示了一个。下面来将UNION替换成UNION ALL看看是什么结果:
SELECT Name FROM Person_1 UNION ALL SELECT Name FROM Person_2
Except 查询形成差集
Except可以对两个或多个结果集进行连接,形成“差集”(前者-后者)。其限定条件为:
- 子结果集要具有相同的结构。
- 子结果集的列数必须相同。
- 子结果集对应的数据类型必须可以兼容。
- 每个子结果集不能包含 order by 和 compute 子句。
其语法形式为:
select_statement except select_statement
该语句将自动删除重复行。实例如下:
SELECT Name FROM Person_1 EXCEPT SELECT Name FROM Person_2
InterSect 查询形成交集
InterSect可以对两个或多个结果集进行连接,形成“交集”。其限制条件为:
- 子结果集要具有相同的结构。
- 子结果集的列数必须相同。
- 子结果集对应的数据类型必须可以兼容。
- 每个子结果集不能包含 order by 或 compute 子句。
其语法形式为:
select_statement intersect select_statement
实例如下:
SELECT Name FROM Person_1 INTERSECT SELECT Name FROM Person_2
嵌套查询
在 SQL 语言中,一个 SELECT-FROM-WHERE 语句称为一个查询块
。将一个查询块嵌套在另一个查询块的 WHERE 子句或 HAVING 短语的条件中的查询称为嵌套查询
。例如:
SQL 语言允许多层嵌套查询。即一个子查询中还可以嵌套其他子查询。需要特别指出的是:子查询的 SELECT 语句中不能
使用 ORDER BY 子句,ORDER BY 子句
只能对最终查询结果排序。
嵌套查询使我们可以用多个简单查询构成复杂的查询,从而增强 SQL 的查询能力。以层层嵌套的方式来构造程序正是 SQL 中“结构化”的含义所在。
带有 IN 谓词的子查询
在嵌套查询中,子查询的结果往往是一个集合,所以谓词 IN 是嵌套查询中最经常使用的谓词。
可见,实现同一个查询可以有多种方法,当然不同的方法其执行效率可能会有差别,甚至差别很大。这就是数据库编程人员应该掌握的数据库性能优化技术。
有些嵌套查询可以用连接运算代替,有些事不能替代的。对于可以用连接运算代替嵌套查询的,到底采用哪种方法得看效率和个人习惯。
带有比较运算符的子查询
带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。当用户能确切知道内存查询返回的是单值时,可以用比较运算符。
求解相关子查询
不能像求解不相关子查询那样一次将子查询求解出,然后求解父查询。内存查询由于与外层查询有关,因此必须反复求值。
带有 ANY(SOME)或 ALL 谓词的子查询
子查询返回单值可以用比较运算符,但返回多值时要用 ANY(有的系统用 SOME)或 ALL 谓词修饰符。而使用 ANY 或 ALL 谓词时则必须同时使用比较运算符。其语义为:
带有 EXISTS 谓词的子查询
EXISTS 代表存在谓词,带有 EXISTS 谓词的子查询不返回任何数据,只产生逻辑 true 或 false。可以利用 EXISTS 来判断属于、子集、集合相等、是否有交集等。
使用存在谓词 EXISTS 后,若内层查询结果非空,则外层的 WHERE 子句返回真值,否则返回假值。
由 EXISTS 引出的子查询,其目标列表表达式通常都用*
,因为带 EXISTS 的子查询值返回逻辑值,给出列名无实际意义。
与 EXISTS 谓词相对应的是 NOT EXISTS 谓词。使用存在谓词 NOT EXISTS 后,若内层查询结果为空,则外层的 WHERE 子句返回真真,否则返回假值。
由于带 EXISTS 谓词的相关子查询只关心内层查询是否有返回值,并不需要查具体值,因此其效率并不一定低于不相关子查询,有时是高效的方法。
数据更新
数据更新操作有 3 种:向表中添加若干行数据、修改表中的数据和删除表中的若干行数据。在 SQL 中有相应的三类语句。
插入数据
SQL 的数据插入语句 INSERT 通常有两种形式。一种是插入一个元组,另一种是插入子查询结果。后者可以一次插入多个元组。
插入元组
插入元组的 INSERT 语句的格式为:
INSERT
INTO <表名> [(<属性列 1>[,<属性列 2>...])]
VALUES(<常量 1>[,<常量 2>]...);
其功能是将新元组插入指定表中。其中新元组的属性列 1 的值为常量 1,属性列 2 的值为常量 2,…。INTO 子句中没有出现的属性咧,新元组在这些列取空值。但必须 注意的是,在表定义时说明了 NOT NULL 的属性列不能取空值,否则会出错。
如果 INTO 子句中没有指明任何属性列名,则新插入的元组必须在每个属性列上均有值。
插入子查询结果
子查询不仅可以嵌套在 SELECT 语句中,用以构造父查询的条件,也可以嵌套在 INSERT 语句中,用以生成要插入的批量数据。插入子查询结果的 INSERT 语句的格式为:
INSERT
INTO <表名> [(<属性列 1> [,<属性列 2>...])]
子查询;
修改数据
修改操作又称为更新操作,其语句的一般格式为:
UPDATE <表名>
SET <列名>=<表达式>[,<列名>=<表达式>]...
[WHERE <条件>];
其功能是修改指定表中满足 WHERE 子句条件的元组。其中 SET 子句给出<表达式>
的值用于取代相应的属性列值。如果省略 WHERE 子句,则表示要修改表中所有元组。
修改某一个元组的值
修改多个元组的值
带子查询的修改语句
删除数据
删除语句的一般格式为:
DELETE
FROM <表名>
[WHERE <条件>];
DELETE 语句的功能是从指定表中删除满足 WHERE 子句条件的所有元组。如果省略 WHERE 子句,表示删除表中全部元组,但表的定义仍在字典中。也就是说,DELETE 语句 删除的是表中的数据,而不是关于表的定义。
删除某一个元组的值
删除多个元组的值
带子查询的删除语句
对某个基本表中数据的增、删、改操作有可能会破坏参照完整性(要求通过定义的外关键字和主关键字之间的的引用规则来约束两个关系之间的联系。这条规则要求“不引用不存在的实体”)。
更新视图
更新视图是指通过视图来插入(INSERT)、删除(DELETE)和修改(UPDATE)数据。
由于视图是不实际存储数据的虚表,因此对视图的更新,最终要转换为对基本表的更新。像查询视图那样,对视图的更新操作也是通过视图消解,转换为对基本表的更新操作。
为防止用户通过视图对数据进行增加、删除、修改时,有意无意地对不属于视图范围内的基本表数据进行操作,可在定义视图时加上 WITH CHECK OPTION 子句。这样 在仕途上增删改数据时,RDBMS 会检查视图定义中的条件,若不满足条件,则拒绝执行该操作。
在关系数据库中,并不是所有的视图都是可更新的,因为有些视图的更新不能位移地有意义地转换成对相应基本表的更新。
一般地,行列子集视图是可更新的。除行列子集视图外,还有些视图理论上是可更新的,但它们的确切特征还是尚待研究的课题。还有些视图从理论上就是不可更新的。
目前各个关系数据库系统一般都只允许对行列子集视图进行更新,而且各个系统对视图的更新还有更进一步的规定,由于各系统实现方法上的差异,这些规定也不仅相同。
应该指出的是,不可更新
和不允许更新
的视图是两个不同的概念。前者是指理论上已证明其是不可更新的视图。后者指实际系统中不支持其更新,但它本
身可能是可更新的视图。
查询优化
查询优化一般可分为代数优化
和物理优化
。
- 代数优化
代数优化是指关系代数表达式的优化。
- 物理优化
物理优化则是指存取路径和底层操作算法的选择。
优化技术:
主要由四种查询优化技术,即启发式关系代数优化方法、启发式关系演算优化方法、基于复杂性的查询优化方法和语义优化方法。本文没有讲到的方法可以自行查询资料。
查询处理
在进行查询优化之前需要对查询处理的基本过程有一个基本的了解,才能对每一个处理过程进行优化,以达到最好的优化效果。查询处理的任务是把用户提交给 RDBMS 的 查询语句转换为高效的执行计划。
查询处理步骤
RDBMS 查询处理可分为 4 个阶段:查询Fenix、查询检查、查询优化和查询执行。
- 查询分析
首先,对查询语句进行扫描、词法分析和语法分析。从查询语句中识别出语言符号,如 SQL 关键字、属性名和关系名等,进行预压检查和语法分析,即判断查询语句是否 符合 SQL 语法规则。
- 查询检查
根据数据字典对合法的查询语句进行语义检查,即检查语句中的数据库对象,如属性名、关系名、是否存在和是否有效。还要根据数据指点中的用户权限和完整性约束定义
对用户的存取权限进行检查。如果该用户没有响应的访问权限或违反了完整性约束,就拒绝执行该查询。检查通过后便把 SQL 查询语句转换成等价的关系代数表达式。
RDBMS 一般都用查询树
,也称为语法分析树
,来表示扩展的关系代数表达式。这个过程中要把数据库对象的外码名称转换为内部表示。
- 查询优化
每个查询都会有许多可供选择的执行策略和操作算法,查询优化
的层次一般可分为代数优化和物理优化。代数优化
是指关系代数表达式的优化,即按照一定的
规则,该表代数表达式中的操作的次序和组合,使查询执行更高效;物理优化
则是指存取路径和底层操作算法的选择。选择的依据可以是基于规则的,也可以是基于
代价的,还可以基于语义的。
实际的 RDBMS 中的查询优化器都综合运用了这些优化技术,以获得最好的查询优化效果。
- 查询执行
依据优化器得到的执行策略生成查询计划由代码生成器
生成执行这个查询计划的代码。
实现查询操作的算法示例
以下以选择操作和连接操作的实现算法(实际为算法思想)为例,介绍查询操作的实现技术。其实,每一种操作有多重执行这个操作的算法,这里仅仅介绍最主要的几个 算法。
选择操作的实现
SELECT 语句功能十分强大,有许多选项,因此实现的算法和优化策略也很复杂。不失一般性,下面以简单的连接操作为例介绍典型的实现方法。
- 简单的全表扫描方法
对查询的基本表顺序扫描,逐一检查每个元组是否满足选择操作,把满足条件的元组作为结果输出。对于小表,这种方法简单有效。对于大表顺序扫描十分费时,效率很低。
- 索引(或散列)扫描方法
如果选择条件中的属性上有索引(例如 B+ 树索引或 Hash 索引),可以用索引扫描方法。通过索引先找到满足条件的元组主码或元组指针,再通过元组指针直接在查询 的基本表中找到元组。
连接操作
连接操作时查询处理中最耗时的操作之一。不失一般性,这里只讨论等值连接(或自然连接)最常用的算法。
- 嵌套循环方法
这是最简单可行的算法。对外层循环(Student)的每一个元组(s),检索内层循环(SC)中的每一个元组(sc),并检查者两个元组在连接属性(sno)上是否相等。如果满足连接条件, 则串联后作为结果输出,直到外层循环表中的元组处理完为止。
- 排序-合并方法
这也是常用的算法,尤其适合连接的诸表已经排好序的情况。用排序-合并连接方法的步骤是:
- 索引连接方法
用索引连接方法的步骤是:
- HASH Join 方法
把连接属性作为 hash 码,用统一 hash 函数把 R 和 S 中元组散列到统一个 hash 文件中。
- (1)第一步,划分阶段,对包含较少元组的表(比如 R)进行一遍处理,把它的元组按 hash 函数分散到 hash 表的桶中;
- (2)第二步,试探阶段,也称为连接阶段,对另一个表(S)进行一遍处理,把 S 的元组散列到适当的 hash 桶中,并把元组与桶中所有来自 R 并与之相匹配的元组 连接起来。
关系数据库的查询优化综述
关系系统的查询优化既是 RDBMS 实现的关键技术又是关系系统的优点所在。它减轻了用户选择存取路径的负担。用户只要提出“干什么”,不必指出“怎么干”。对比一下 非关系系统中的情况:
用户使用过程化语言表达查询要求,执行何种记录级的操作,以及操作的序列是由用户而不是由系统来决定的。因此用户必须了解存取路径,系统要提供用户选择存取路径 的手段,查询效率由用户的存取策略决定。如果用户做了不当的选择,系统是无法对此加以改进的。这就要求用户有较高的数据库技术和程序设计水平。
查询优化概述
查询优化的优点不仅在于用户不必考虑如何最好地表达查询以获得较好的效率,而且在于系统可以比用户程序的“优化”做得更好。这是因为:
(1)优化器
可以从数据字典中获取许多统计信息,例如每个关系表中的元组树、关系中每个属性值得分布情况、哪些属性上已经建立了索引等。优化器可以根据
这些信息做出正确的估算,选择高校的执行计划,而用户程序则难以获得这些信息。
(2)如果数据库的物理统计信息改变了,系统可以自动对查询进行重新优化以选择相适应的执行计划。在非关系系统中必须重写程序,而重写程序在实际应用中往往是 不太可能的。
(3)优化器可以考虑数百种不同的执行计划,而程序员一般只能考虑有限的几种可能性。
(4)优化器中包括了很多复杂的优化技术,这些优化技术往往只有最好的程序员才能掌握。系统的自动化优化相当于使得所有人都拥有了这些优化技术。目前 RDBMS 通过 某种代价模型计算出各种查询执行策略的执行代价,然后选取代价最小的执行方案。在集中式数据库中,查询的执行开销主要包括磁盘存取块数(I/O 代价),处理机时间 (CPU 代价),查询的内存开销。在分布式数据库中还要加上通信代价。
一般地,集中式数据库中 I/O 代价是最主要的。查询优化的总目标是:选择有效的策略,求得给定关系表达式的值,使得查询代价最小(实际上是较小)。
一个实例
启发式关系代数优化方法
在很多数据库管理系统中,查询处理的第一步是把查询变换为与关系代数对应的内部表示,如查询树,一个查询可以变换为一个等价的关系代数表达式。
关系代数等价变换规则
启发式代数优化规则
物理优化
代数优化改变查询语句中操作的次序和组合,不涉及底层的存取路径。对每一种操作有多重执行这个操作的算法,有多条存取路径。因此对于一个查询语句有许多存取方案,
它们的执行效率不同,有的会相差很大。因此,仅仅进行代数优化是不够的。物理优化
就是要选择高效合理的操作算法或存取路径,求得优化的查询计划,达到查询
优化的目标。
选择的方法可以是:
- 基于规则的启发式优化:
启发式规则
是指那些那些在大多数情况下都适用,但不是在每种情况下都是适用的规则。
- 基于代价估算的优化:
优化器估算不同执行策略的代价,并选出具有最小代价的执行计划。
- 两者结合的优化方法:
查询优化器通常会把这两种技术结合在一起使用。因为可能的执行策略很多,要穷尽所有的策略进行代价估算往往是不可行的,会造成查询优化本身付出的代价大于获得 的益处。谓词,常常先使用启发式规则,选取若干较优的候选方案,减少代价估算的工作量;然后分别计算这些候选方案的执行代价,较快地选出最终的优化方案。
基于启发式规则的存取路径选择优化
选择操作的启发式规则有:
- 对于小关系,使用全表顺序扫描,即使选择列上有索引。
对于大关系,启发式规则有:
- 对于选择条件是主码 = 值的查询,查询结果最多是一个元组,可以选择主码索引。一般的 RDBMS 会自动建立主码索引。
- 对于选择条件是非主属性 = 值得查询,并且选择列上有索引,则要估算查询结果的元组数目,如果比例较少可以使用索引扫描方法,否则还是使用全表扫描。
- 对于选择条件是属性上的非等值查询或者范围查询,并且选择列上有索引,处理同上。
- 对于用 AND 连接的合取选择条件,如果有涉及这些属性的组合索引,则优先采用组合索引扫描方法;如果某些属性上有一般的索引,则可以用前面介绍过的索引扫描 方法(参见“实现查询操作的算法示例”),否则使用全表扫描。
- 对于用 OR 连接的析取选择条件,一般使用全表顺序扫描。
连接操作的启发式规则有:
- 如果 2 个表都已经按照连接属性排序,则选用排序-合并方法。
- 如果一个表在连接属性上有索引,则可以选用索引连接方法。
- 如果上面 2 个规则都不适用,其中一个表较小,则可以选用 Hash Join 方法。
- 最后可以选用嵌套循环方法,并选择其中较小的表,确切地讲是占用的块数较少的表,作为外表(外循环的表)。理由如下:
上面列出了一些主要的启发式规则,在实际的 RDBMS 中启发式规则要多得多。
基于代价的优化
数据库的完整性
数据库运行时,应防止输入或输出不符合语义的错误数据,而始终保持其中数据的正确性。这就是通常所说的数据库的完整性
。数据库的完整性可分为系统自身规定
的完整性(如实体完整性、引用完整性等),用户自定义完整性。
数据完整性和安全性的概念辨析:
- 数据完整性
数据完整性
是为了防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据。完整性检查和控制的防范对象是不合语义的、不正确的数据,防止
它们进入数据库。
- 数据安全性
数据的安全性
是保护数据库数据防止恶意的破坏和非法的存取。安全性控制的防范对象是非法用户和非法操作,防止他们对数据库非法存取。
为维护数据库的完整性,DBMS 必须能够:
- 提供定义完整性约束条件的机制
完整性约束条件也称为完整性规则
,是数据库中的数据必须满足的语义约束条件。SQL 标准使用了一系列概念来描述完整性,包括关系模型的实体完整性、参照完整性
和用户定义完整性。这些完整性一般由 SQL 的 DDL 语句来实现。它们作为数据库模式的一部分存入数据字典中。
- 提供完整性检查的方法
DBMS 中检查数据是否满足完整性约束条件的机制称为完整性检查
。一般在 INSERT、UPDATE、DELETE 语句执行后开始检查,也可以在事务提交时检查。检查这些操作
执行后数据库中的数据是否违背了完整性约束条件。
- 违约处理
DBMS 若发现用户的操作违背了完整性约束条件,就采取一定的动作,如拒绝(NO ACTION)执行该操作,或级连(CASCADE)执行其他操作,进行违约处理以保证数据的完整性。
完整性控制
数据库中的完整性控制可以由应用程序编写程序来实现数据自己的完整性,也可以通过数据库自带完整性约束来实现。用完整性约束来实现数据完整性比用应用程序来进行 完整性控制更可靠更高效。完整性约束是用一些股则来限制在一个表中某(些)列,是一种保证数据库数据一致性和有效性的一种手段。
完整性约束语句一般出现在创建表(视图)或修改表(视图)语句中,用于影响列的定义和某些条件的定义。完整性控制按照完整性约束是否具有修复数据能力分为两大类:
- (1)声明型完整性约束
声明型完整性约束
是指通过使用声明性的约束子句在 DDL 语句中声明了约束,一旦违反约束的数据操作发生后,只需由系统简单地对该数据操作进行禁止。
声明型完整性约束主要分为:
- 域完整性约束:
- 非控制约束(NOT NULL)
- CHECK 约束
- 参照完整性约束:
- 主键约束
- 唯一性约束(候选键约束)
- 外键约束等
-
全局约束。
- (2)处理型完整性约束:
处理型完整性约束
是指在约束的定义过程中,不仅声明了某个约束,而且这个约束的具体规则及处理行为系统并没有实现,需要数月本身用代码来实现。实现后的约束
具有很多的灵活性,而不是简单地对数据操作做禁止与允许处理。从维护数据完整性的意义上看,处理型的完整性约束是应用程序维护数据完整性的一种特例(不过还是
有些不同)。不同的是在维护数据完整性的时候约束是系统强制执行的,而应用程序是由用户自定义执行的。常用的处理型完整性主要是触发器
。处理型完整性约束
同声明型完整性约束相比,能够实现更为复杂的检查和操作,从而保证数据库数据的一致性。但是,因为触发器很容易造成级联调用
,而且实现相同约束效率要比声明
型约束差,应合理利用而不能滥用。
实体完整性
关系模型的实体完整性在 CREATE TABLE
中用 PRIMARY KEY
定义。对单属性构成的码有两种说明方法:
- 列级约束条件;
- 定义为表级约束条件。
对多个属性构成的码只有一种说明方法,即定义为表级约束条件。
实体完整性检查和违约处理
用 PRIMARY KEY 短语定义了关系的主码后,每当用户程序对基本表插入一条记录或者对主码列进行更新操作时,RDBMS 将利用实体性完整性规则自动进行检查,包括:
- 检查主码值是否唯一,如果不唯一则拒绝插入或修改。
- 检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改。
从而保证了实体完整性。检查记录中主码值是否唯一的方法:
参照完整性
关系模型的参照完整性在 CREATE TABLE
中用FOREIGN KEY
短语定义哪些列为外码,用 REFERENCES
短语指明这些外码参照哪些表的主码。
参照完整性检查和违约处理
一个参照完整性将两个表中的相应元组联系起来了。因此,对被参照表和参照表进行增删改操作时有可能破坏参照完整性,必须进行检查。
当上述的不一致发生时,系统可以采用以下的策略加以处理。
- 拒绝执行:不允许操作执行。该策略一般设置为默认策略。
- 级连操作:
当删除或修改被参照表的一个元组造成了与参照表的不一致,则删除或修改参照表中的所有造成不一致的元组。
- 设置为空值:
当删除或修改被参照表的一个元组时造成了不一致,则将参照表中的所有造成不一致的元组的对应属性设置为空值。不过不是所有的外码都可以接受空值(比如学号)。 因此对于参照完整性时,除了应该定义外码,还应定义外码是否允许空值。
一般地,当对参照表和被参照表的操作违反了参照完整性,系统选用默认策略,即拒绝执行。如果想让系统采用其他的策略则必须在创建表的时候显式地加以说明。
可以对 DELETE 和 UPDATE 采用不同的策略。如,对删除操作违反一致性时拒绝执行;对更新操作则采取级连更新的策略。
断言约束
断言,在数据库中用 assertion 谓词
来实现。其实,有关的域完整性约束和参照完整性约束都是一种特殊的断言约束。这些约束都容易检测和表达,所以在很多的
数据库中比价适用。但是,还有许多数据完整性约束并不那么容易检测和表达,但是确实又是在现实中存在的,我们可以断言来进行处理。断言是数据库模式(schema)级
的约束,一旦涉及的关系发生变化时系统将自动检测。
断言的语法为:
CREATE ASSERTION <name> CHECK (<condition>);
断言一旦建立,那么在整个数据库中,任何有违背断言的数据操作即将被禁止。这样很方便使数据库按照应用系统的业务规则做数据间的平衡关系,但是如果这种平衡关系 设计得太复杂,将为系统在做出是否违背断言的规则检测时,变得相当的吃力,这是也大大滴损耗了数据库的许多宝贵资源。因此,应慎用断言。
用户定义的完整性
用户定义完整性就是针对某一具体应用的数据必须满足的语义要求。目前的 RDBMS 都提供了定义和检验这类完整性的机制,使用了和实体完整性,参照完整性相同的技术 和方法来处理它们,而不必由应用程序承担这一功能。
属性上的约束条件的定义
在 CREATE TABLE
中定义属性的同时可以根据应用要求,定义属性上的约束条件,即属性值限制,包括:
- 列值非空(NOT NULL 短语)
- 列值位移(UNIQUE 短语)
- 检查列值是否满足一个布尔表达式(CHECK 短语)
例子
- 不允许取空值
- 列值唯一
- 用 CHECK 短语指定列值应该满足的条件
属性上的约束条件检查和违约处理
当往表中插入元组或修改属性的值时,RDBMS 就检查属性上的约束条件是否被满足,如果不满足则操作被拒绝执行。
元组上的约束条件的定义
与属性上约束条件的定义类似,在 CREATE TABLE
语句中可以用 CHECK 短语
定义元组上的约束条件,即元组级的限制。同属性值限制相比,元组级的限制可以
设置不同属性之间的取值的相互约束条件。
元组上的约束条件检查和违约处理
当往表中插入元组或修改属性的值时,RDBMS 就检查元组上的约束条件是否被满足,如果不满足则操作被拒绝执行。
完整性约束命名子句
前面讲解的完整性约束条件都在 CREATE TABLE
语句中定义。SQL 还在 CREATE TABLE 语句中提供了完整性约束命名子句 CONSTRAINT
,用来对完整性约束条件
命名。从而可以灵活地增加、删除一个完整性约束条件。
完整性约束命名子句
CONSTRAINT <完整性约束条件> [PRIMARY KEY 短语|FOREIGN KEY 短语|CHECK 短语]
修改表中的完整性限制
可以使用 ALTER TABLE 语句修改(更新)表中的完整性限制。
域中的完整性限制
SQL 支持域的概念,并可以用 CREATE DOMAIN
语句建立一个域以及该域应该满足的完整性约束条件。
触发器
在很多情况下,当一个完整性约束被违背时,数据库管理系统除了终止事务外,还需要执行一些其他操作。例如,通知某个用户完整性约束被违背,又例如,每当雇员的差旅
费超过了某一限制时,需要通知经理来处理。为了在数据库完整性约束被违背时能够及时地执行必要的操作,数据库工作者提出了触发器
技术。
触发器概述
约束有其执行模式,每当约束的元素(比如属性,元组)发生变化时,就按其执行模式调用相应的约束。由于约束的实现设计到对相应事件的检验进行“触发”,因此,人们 很自然地会想到,能否由数据库编程人员而不是由系统来选择出发事件。这种方法可为用户提供某些附加的选项,以便有针对性地出发数据库操作,而不是被动地防止出现 约束的违例。
为此,SQL3 的推荐标准包括“触发”。说到触发
很容易联想到约束
,但触发程序(实现触发机制的程序)要明确指定触发事件,并明确指定基于条件真假而要
做的动作。如果说约束还有一定被动性的话,那么触发就完全是主动性元素。
触发有时也称为事件-条件-动作规则
或 ECA 规则
。触发与约束在以下三个方面有所不同:
(1)当数据库编程人员所指定的某个或某些事件发生时才对触发程序进行测试。允许的事件通常为对特定关系的插入、删除或修改。另一种允许的事件为事务结束。
(2)不是直接阻止事件的发生,而是由处罚程序对条件进行测试。如果条件不满足则什么也不做,否则,为响应该事件就会进行与该触发相关的处理。
(3)如果出发条件得到满足,就由 DBMS 执行与该触发相关的动作。于是,该动作可能阻止事件的发生或撤销时间(如删除插入的元组)。实际上,动作可能是数据库操作 的任何序列,甚至可能是与触发事件毫不相干的操作。
SQL3 的触发语句
在时间、条件和动作部分给用户许多不同的选项。其主要特点如下:
- 动作可以在触发事件之前、之后执行,甚至可以不通过触发事件而执行;
- 动作可以引用在触发该动作的事件中插入、删除或修改的元组的旧值或新值;
- 修改事件可以指定特定的属性或属性集;
- 条件可以用 WHEN 子句来执行,而只有在对规则进行触发并且当触发事件发生时条件满足的情况下动作才会执行;
- 编程人员可以对规定执行的动作进行如下选择:
- 对每个更新的元组都执行一次;
- 对在一个数据库操作中发生变化的所有元组执行一次。
触发器组成
触发器是存储在数据库里的过程,当数据库某事件发生时,这个过程就会被 DBMS 在后台自动运行。与过程或函数不同的是:触发器不接受参数,除了能完成声明型约束 不能完成的数据完整性控制的功能外,触发器还可以做许多事,包括审计表中信息被修改时记录修改者的行为,自动为其他程序发信号等。一个触发器由 4 个部分组成:
- 触发器侦测的操作事件(如,删除记录等);
- 操作事件的对象(如,列、表等)
- 触发时是否执行触发器执行体的先决条件(如,数据修改时新值不等于旧值等);
- 触发器执行体(与自定义存储过程一样的业务逻辑处理)。
触发器分类
根据触发器侦测的操作事件和操作事件的对象不同,可将触发器分为以下类型:
- DML 触发器:由 DML 数据操作语句触发的触发器,是最常用的一种触发器;
- 系统触发器:由对数据库或模式对象的操作而触发的触发器,分数据库级和模式级两种类型;
- 替代触发器:由对视图对象进行数据更新操作而触发的触发器。
DML 触发器
DML 触发器
是数据库系统传统意义上的触发器,一般由三类数据操作事件触发:数据插入(Insert)、数据修改(Update)、数据删除(Delete)。
- 语法:
- 对上述语法的说明:
- 举例:
系统触发器
系统触发器主要用于对数据库和模式对象的操作事件进行侦测,主要侦测的具体事例有:
- 数据库级:数据库的启动、关闭、登录、退出、服务器出错;
- 模式级:创建对象、修改对象、删除对象。
下面从语法方面进行简单阐述和说明。
- 语法:
- 对语法的说明:
- 举例:
替代触发器
替代触发器
主要用于侦测视图数据的操作事件。对于可修改数据的视图才有必要定义一个替代触发器。替代触发器只能再行级上触发,不能上升到语句级,只能被
创建在视图上,不能加 BEFORE/AFTER 选项,在对视图进行 INSERT 或 UPDATE 操作时候,系统将自动检查替代触发器是否执行。
- 语法:
- 对语法的说明:
除使用 instead of 和指定 view_name 外,其他说明与 DML 触发器意义一致。
- 举例:
删除触发器
触发程序举例
触发程序可分为元组级
(又称为行级)触发程序和语句级
触发程序两类。两者的差别是:
- 形式上:
前者有 FOR EACH ROW
子句,而后者没有。
- 执行上:
对于产生多个触发事件(更新多个元组)的一个 SQL 更新语句,前者对每个元组都执行一次,而后者只对整个语句执行一次。
- 应用时:
前者可直接引用旧元组或新元组,而后者只能引用旧元组的集合(删除的元组或修改的元组的旧版本)和新元组的集合(插入的元组或修改的元组的新版本)。
下面是一个引用元组集的例子。
其他实例:
层次与网状数据库系统
层次与网状数据库系统是最早出现的数据库系统,被称为第一代数据库系统
,正逐渐被关系数据库系统取代,但目前在美国等一些国家里,由于历史的原因,这两类
数据库系统的用户仍然很多。
层次数据库系统
层次数据系统是基于层次数据模型的数据库系统。下面简单介绍层次数据库的数据定义、数据操纵、存储结构等内容。
层次数据模型中的数据结构
层次数据模型具有两个主要的数据结构概念,即记录
和父子联系
。一个记录是一组数据域的集合。每个数据域
可以存储一个数据值。具有相同结构的记录
集合构成一个记录型
,一个记录型具有一个名字。记录型的数据结构由一组命名的数据域
或数据项
定义。每个数据域具有一个数据类型,如整数、字符串等。
M:N 联系的表示
层次数据模型只能直接表示两个记录之间的 1:N 联系,在显示世界中,M:N(多对多)联系也是非常重要的联系。如果记录型 R 和 S 之间存在一个 M:N 父子联系型,则每个 R 型记录对应于多个 S 型记录,反之,每个 S 型记录也对应于多个 R 型记录。下面,介绍两种使用层次数据模型表示 M:N 联系的方法。
数据操作
完整性约束
IMS 概述
网状数据库系统
网状数据模型是一种比层次数据模型更具普遍性的数据模型,取消了层次数据模型的树形数据结构的限制,允许没有父节点的节点存在,允许一个节点有多个父节点,允许
两个节点之间有多重联系(称之为复合联系
)。因此网状数据模型可以更直接地描述现实世界。层次数据模型是网状数据模型的一个特例。
数据结构
网状数据模型的数据结构是层次数据结构的扩充。在层次数据结构中,每个子记录有且仅有一个父记录。在网状数据结构中,一个子记录可以有任意数量的父记录,包括没有
父记录的情况。网状数据模型具有两个基本数据结构:记录
和系
。
一个记录是一组数据域的集合。每个数据域
可以存储一个数据值。具有相同结构的记录集合构成一个记录型
,一个记录型具有一个名字。
记录型的数据结构由一组命名的数据域
或数据项
定义。每个数据域具有一个数据类型,如整数、字符串等。记录是记录型的实例
。
在网状模型中,记录型描述的是现实世界的实体,数据项描述实体的属性,每个记录型具有一个或一组数据项作为键
,唯一地标识记录。
关系和层次数据模型只允许简单数据项,网状数据模型支持两类复杂数据项,即向量和重复组,向量
是一个记录中由多个相同类型的数据值构成的数据项。重复组
是一个记录中由多种类型的多个数据值构成的一个数据项。
上面的各种数据项称为实数据项
,因为它们是实际存储在记录中的数据项。虚数据项
是由实数据项定义或推导出的数据项。虚数据项不在记录中存储。例如,我们
可以在 STUDENT 记录型上定义一个虚数据项 AGE,并写一个从这个记录型的数据项 BIRTHDAYE 计算 AGE 的过程。
一个数据库应用通常具有大量的记录型。不同记录型的记录一般都相互关联。为了描述这些关联,网状数据模型提供了一种结构—-系
。
数据操作
完整性约束
三个特殊的系型
网状数据模型具有三个特殊系型,即系统系型、多成员系型和递归系型。
M:N 联系的表示
数据库设计
人们在总结信息资源开发、管理和服务的各种手段时,认为最有效的是数据库技术。
什么是数据库设计呢?
广义地讲,数据库设计
是数据库及其应用系统的设计,即设计整个的数据库应用系统。狭义地讲,是设计数据库本身,即设计数据库的各级模式并建立数据库,这是
数据库应用系统设计的一部分。这里重点讲狭义的数据库设计。
数据库设计
是指对于一个给定的应用环境,构造(设计)优化的数据库逻辑模式和物理结构,并据此建立数据库及其应用系统,使之能够有效地存储和管理数据,满足
用户的应用需求,包括信息管理要求和数据操作要求。
其中信息管理要求
是指在数据库中应该存储和管理哪些对象;数据操作要求
是指对数据对象需要进行哪些操作,如查询、曾、删、该、统计等操作。
概述
设计与使用数据库刺痛的过程是把现实世界的数据经过人为的加工和计算机的处理,又为现实世界提供信息的过程。在给定的 DBMS、操作系统和硬件环境下,表达用户的需求,
并将其装换为有效的数据库结构,构成较好的数据库模式,这个过程称为数据库设计
。要设计一个好的数据库必须用系统的观点分析和处理问题。数据库及其应用系统
开发的全过程可分为两大阶段:数据库系统的分析与设计阶段;数据库系统的实施、运行与维护阶段。
在数据库设计中面临的主要困难和问题有:
- 同时具备数据库知识与应用业务知识的人很少。懂计算机与数据库的人一般都缺乏应用业务知识和实际经验,而熟悉应用业务的人又往往不懂计算机和数据库。
- 项目初期往往不能确定应用业务的数据库系统的目标。
- 缺乏完善的设计工具和设计方法。
- 需求的不确定性。用户总是在系统的开发过程中不断提出新的要求,甚至在数据库建立之后还会要求修改数据库结构或增加新的应用。
- 应用业务系统千差万别,很难找到一种适合所有业务的工具和方法,这就增加了研究数据库的自动生成工具的难度。因此,研制适合一切应用业务的全自动数据库生成 工具几乎是不可能的。
完善的数据库系统应具备如下特点:
- 功能强大;
- 能准确地表示业务数据;
- 使用方便,易于维护;
- 便于检索和修改数据;
- 在合理的时间内响应最终用户的操作;
- 为以后改进数据库结构留下空间;
- 维护数据库的工作较少;
- 具备有效的安全机制来确保数据安全;
- 冗余数据最少或不存在;
- 便于进行数据的备份和恢复;
- 数据库结构对最终用户透明。
数据库设计问题
数据库设计所要解决的问题是:对于一个给定的应用领域,设计优化的数据库逻辑和物理结构,使之满足用户的信息管理要求和数据操作要求,有效地支持各种应用系统的
开发和运行。数据库设计的目标是为用户和各种应用系统提供一个高效率的运行环境。效率包括两个方面:一是数据库的存取效率
,二是存储空间的利用率
。
数据库设计可以视为以下的优化问题:
约束条件:
- 计算机软硬件环境;
- 数据库管理系统的能力;
- 用户的操作要求与信息要求;
-
完整性和安全性约束。
目标函数:
数据设计问题:
数据库设计的任务
数据库的生命周期可分为两个重要的极端:一是数据库的设计阶段,二是数据库的实施和运行阶段。其中数据库的设计阶段是数据库整个生命周期中工作量比较大的一个阶段, 其质量对整个数据库系统的影响很大。
数据库设计的主要任务
是:根据一个单位的信息需求、处理需求和数据库的支撑环境(包括 DBMS,操作系统和硬件),设计出数据模式(包括外模式、逻辑(概念)
模式和内模式)以及典型的应用程序。其中信息需求
表示一个单位所需要的数据及其结构。处理需求
表示一个单位需要经常进行的数据处理,例如工资计算、
成绩统计等。前者表达了对数据库的内容及结构的要求,也就是静态要求;后者表达了基于数据库的数据处理要求,也就是动态要求。DBMS、操作系统和硬件是建立数据库的
软、硬件基础,也是其制约因素。
信息需求
主要是定义所设计的数据库将要用到的所有信息,描述实体、属性、联系的性质。描述数据之间的联系。处理要求
则定义锁设计的数据库将要进行的数据处理,
描述操作的优先次序、操作执行的频率和场合,描述操作与数据之间的联系。当然,信息需求和处理需求的区分不是绝对的,只不过侧重点不同而已。信息需求要反映处理的
需求,处理需求自然包括其所需要的数据。
数据库设计方法:
数据库设计有两种不同的方法:瞄向数据的设计方法、面向过程的设计方法。
- 面向数据的设计方法:
面向数据的设计方法
以信息需求为主,兼顾处理需求。用这种方法设计的数据库,可以比较好地反映数据的内在联系,不但可以满足当前应用的需要,
还可以满足潜在的应用的需求。
在实际应用中,数据库一般由许多用户共享,还可能不断有新的用户加入,除了常规的处理要求外,还有许多即兴的访问。对于这类数据库,最好采用面向数据的设计方法, 使数据库比较合理地模拟一个单位。一个单位的数据重视相对稳定的,而处理测试则是相对变动的。为了设计一个相对稳定的数据库,一般采用面向数据的设计方法。
- 面向过程的设计方法:
面向过程的设计方法
以处理需求为主,兼顾信息需求。用此方法设计的数据库,可能在使用的初始阶段比较好地满足应用的需要,获得好的性能,但随着应用的发展和
变化,往往会导致数据库的较大的表动或者不得不重新设计。
面向过程的设计方法主要用于处理要求比较明确、固定的应用系统,例如酒店管理。
数据库的设计成果:
数据库设计的成果有两个:一是数据模式。二是以数据库为基础的典型应用程序。应用程序是随着应用而不断发展的,在有些数据库系统中(如情报检索),实现很难编出所需 的全部应用程序或事务。因此,数据库设计的最基本的成果是数据模式。不过,数据模式的设计必须适应数据处理的要求,以保证大多数常用的数据处理能够方便、快速地进行。
数据库设计特点
数据库设计的很多阶段都可以和软件工程的各阶段对应起来,软件工程的某些方法和工具同样也适合于数据库工程,但数据库设计还有很多自己的特点。
- 从数据结构即数据模型开始,并以数据模型为核心展开。这是数据库设计的一个主要特点。
- 静态结构设计与动态行为设计分离:
静态结构设计
是指数据库的模式结构设计,包括概念结构、逻辑结构和物理结构的设计。动态行为
设计是指应用程序设计,
包括功能组织、流程控制等方面的设计。传统的软件工程往往注重处理过程的设计,不太注重数据结构的设计,在结构程序设计中只要可能就尽量推迟数据结构的设计,而
数据库设计正好与之相反,需要把主要精力放在数据结构的设计上,如数据库的表结构、视图等。
- 试探性:
数据库设计比较复杂,又缺少完善的设计模型和统一的过程,设计的过程往往是试探性的过程,因此设计的结果往往不是唯一的。有时多种方案并存,供设计者选择,而且 这种选择并不是完全客观的,有时多少取决于用户的偏爱和观点。
- 反复性:由于数据库设计是一种试探性的过程,这就是决定了数据库的设计是一个反复推敲和修改的过程,而不可能“一气呵成”。
- 多步性:
传统的数据库设计采用直观设计法或单步设计法,它由设计者通过对用户的调查访问,确认需求,熟悉用户应用问题的语义,结合结构限制于 DBMS 功能,凭设计人员的经验 进行分析、选择、综合与抽象之后,建立数据模型,并用 DDL 写出模式。由于这种设计方法要求设计人员有比较丰富的经验和熟练的技巧,不易为一般人所掌握,且因缺乏 工程规范支持和科学根据,现已抛弃不用。新的数据库设计是分步(阶段)进行的,前一阶段的设计结果可作为后一阶段设计的依据,后一阶段也可向前一阶段反馈其要求, 反复修改,逐步完善。
数据库建设的基本规律:
“三分技术,七分管理,十二分基础数据”是数据库设计的特点之一。
在数据建设中不仅涉及技术,还涉及管理。要建设好一个数据库应用系统,开发技术固然重要,但是相比之下则管理更加重要。这里的管理不仅仅包括数据库建设 作为一个大型的工程项目本身的项目管理,而且包括该企业(即应用部门)的业务管理。
在数据库建设的长期实践中深刻认识到一个企业数据库建设的过程是企业管理模式的改革和提高的过程。只有把企业管理创新做好,才能实现技术创新,才能建设好一个 数据库应用系统。
十二分基础数据
则强调了数据的收集、整理、组织和不断更新是数据库建设中的重要环节。人们往往忽视基础数据在数据库建设中的地位和作用。基础数据的收集、
入库
是数据库建立初期工作量最大、最繁琐、最细致的工作。在以后数据库运行过程中更需要不断地把新的数据加到数据库中,使数据库称为一个“活库”,否则
就成了“死库”。数据库一旦成了“死库”,系统也就失去了应用价值,原来的投掷也就失败了。
结构(数据)设计和行为(处理)设计相结合:
数据库设计应该和应用系统设计相结合。也就是说,整个设计过程中把数据库结构设计和数据的处理设计密切结合起来。但是早期的数据库应用系统开发过程中,常常把数据 库设计和应用系统的设计分离开来,如下图。
传统的软件工程
忽视对应用中数据语义的分析和抽象。例如结构化设计和逐步求精的方法着重于处理过程的特性,只要有可能就尽量推迟数据结构设计的决策。这种
方法对于数据库应用系统的设计显然是不妥的。
早期的数据库设计致力于数据模型和数据库建模方法的研究,着重结构特性的设计而忽视了行为的设计对结构设计的影响,这种方法也是不妥的。
数据库设计方法
大型数据库设计是涉及多学科的综合性技术,又是一项庞大的工程项目。它要求从事数据库设计的专业人员具备多方面的技术和知识。主要包括:
- 计算机的基础知识;
- 软件工程的原理和方法;
- 程序设计的方法和技巧;
- 数据库的基本知识;
- 数据库设计技术;
- 应用领域的知识。
早期数据库设计主要采用手工与经验相结合的方法,那时数据库设计是一种技艺。谓词,提出了各种通用的数据库设计方法。能够有效地指导数据库设计,使数据库设计
更加合理的原则称为数据库设计方法学
。目前已有的数据库设计方法可分为四类:
- 直观设计法:
直观设计法又称单步逻辑设计法
,它依赖于设计者的知识、经验和技巧,缺乏工程规范的支持和科学依据,设计质量也不稳定。为此,数据库专家在美国新奥尔良市
专门讨论了数据库设计问题,提出了数据库设计规范,把数据库设计分为:需求分析阶段、概念结构设计阶段、逻辑结构设计阶段和物理结构设计阶段四个阶段。目前,
常用的规范设计方法大多起源于新奥尔良方法
。
- 规范设计法;
- 计算机辅助设计法;
- 自动化设计法。
基于 3NF 的数据库设计方法
其基本思想是在需求分析的基础上,识别并确认数据库模式中的全部属性和属性间的依赖,将它们组织成一个单一的关系模式,然后再分析模式中不符合 3NF 的约束条件, 用投影和连接的办法将其分解,使其达到 3NF 条件。其具体涉及步骤分为五个阶段,如下图所示:
(1)设计企业模式,使用上述得到的 3NF 关系模式画出企业模式。具体包括:
- 分析应用环境,并设定环境中所使用的种种资料。
- 确定每一种报表各自所包含的数据元素。
- 确定数据元素之间的关系,如确定主键和一般的数据元素。
- 对每一组或若干组数据元素推导出 3NF 的关系模式。
- 在 3NF 关系模式的基础上画出数据库的企业模式。
(2)设计数据库逻辑模式。
- 根据上一步得到的企业模式选定数据模型,从而得到试用于某个 DBMS 的逻辑模式。
- 根据逻辑模式导出各种报表与事务处理所使用的外模式。
(3)设计数据库物理模式(存储模式
)。根据数据库的逻辑模式和给定的计算机系统设计物理模式。
(4)评价物理模式。
- 对物理模式估算空间利用情况,并推算输入/输出的概率。
- 必要时根据物理模式调整各种报表与实务处理的外模式。
- 对外模式进行存取时间的估算。
(5)数据库实现。
LRA 方法
数据库设计的 LRA 方法即逻辑记录存取法
。它从用户的信息要求和处理要求出发,分三个阶段完成数据库的设计。
- (1)需求分析:
向现有和潜在的用户了解和收集有关的信息内容和处理要求,并将它们文本化。
- (2)逻辑设计:
逻辑设计又分信息结构设计
(ISD)和信息结构改进(ISR)两步。前者主要是分析各种用户的信息要求,确定实体、属性及实体之间的联系,并综合成一个厨师的数据
库信息结构。信息结构改进的主要任务是根据设计的厨师信息结构、处理要求和 DBMS 的特点,设计 DBMS 能处理的模式。它分三步完成:
- 首先定义局部信息结构,并将局部信息结构合并成全局信息结构;
- 然后分别将全局信息结构和局部信息结构转换为 DBMS 所能支持的逻辑数据库结构和局部逻辑数据库结构;
-
最后根据数据传送量、应用的处理拼读、逻辑记录存取数等因素,改进逻辑数据库结构。
- (3)物理涉及:
LRA 方法的物理涉及与其他方法的物理涉及类似。LRA 方法的特点是:提供一种定量估算的方法,使得能够对数据库逻辑结构的性能进行分析,在可供选择的若干个结构
中选择一个处理效率较高的结构,或者据此对现有的逻辑结构进行改进。谓词,LRA 使用逻辑记录存取数
表示在一个应用程序执行过程中对一个记录类型所要查找
的记录的个数,记做 LRA 数。根据所有应用程序的 LRA 数及它们在单位时间内要执行的次数,就可以知道哪些应用程序可能要求的 I/O 次数最多,哪些应用程序在性能上
起着主导地位,从而决定如何改进逻辑结构以提高处理效率。
基于实体联系(E-R)的数据库设计方法
E-R 方法主要用于逻辑设计。其基本思想是在需求分析的基础上,用 E-R 图构造一个纯粹反映现实世界实体之间内在联系的企业模式,然后再将此企业模式转换成选定的 DBMS 上的概念模式。E-R 方法简单易用,又克服了单步逻辑设计方法的一些缺点。因此成为比较流行的方法之一。但由于它主要用于逻辑设计,故 E-R 方法往往成为其他 设计方法的一种工具。
基于视图概念的数据库设计方法
此方法先从分析各个应用的数据着手,为每个应用建立各自的视图,然后再把这些视图汇总起来合并成整个数据库的概念模式。合并时必须注意解决下列问题:
- 消除命名冲突;
- 消除冗余的实体和联系;
- 进行模式重构。
在消除了命名冲突和冗余后,需要对整个汇总模式进行调整使其满足全部完整性约束条件。
面向对象的关系数据库设计方法
面向对象的数据库设计(即数据模式)思想与面向对象数据库管理系统(OODBMS)理论不能混为一谈。前者是数据库用户定义数据库模式的思路,而后者是数据库管理 程序的思路。用户使用面向对象方法学可以定义任何一种 DBMS 数据库,即网络型、层次型、关系型等。对象的数据库设计从对象模型触发,属于实体主导型设计。
数据库设计(模式)是否支持应用系统的对象模型是判断是否是面向对象数据库系统的基本出发点。应用系统对象模型向数据库模式的映射是面向对象数据库设计的核心和 关键,其实质就是向数据库表的变换过程。有关变换规则简单归纳如下:
(1)一个对象类可以映射为一个以上的库表,当类间有一对多关系时,一个表也可以对应多个类。
(2)关系(一对一、一对多、多对多等)的映射可能有多种情况,但一般映射为一个表,也可以在对象类表间定义相应的外键。对于条件关系
的映射,一个表至少应有
三个属性。
(3)单一继承的泛化关系
可以对超类、子类分别映射表,也可以不定义父类表而让子类表拥有父类属性,反之,也可以不定义子类表而让父类拥有全部子类属性。
(4)多重继承的超类和子类分别映射表,对多次多重继承的泛化关系也映射一个表。
(5)对映射后的库表进行冗余控制调整,使其达到合理的关系范式。
面向对象关系数据库设计效果可归纳为:
- 数据库结构清晰,便于实现 OOP;
- 数据库对象具有独立性,便于维护;
- 需求变更时程序与数据库重用率高,修改少。
. 计算机辅助数据库设计方法
计算机辅助数据库设计是数据库设计趋向自动化的一个重要步骤,它的基本思想并不是完全由机器代替人,而是提供一个交互式过程,人机结合,相互渗透,帮助设计者更快 更好地进行设计工作。在数据库设计过程中,目前还没有全自动设计方法,只能使用计算机进行局部辅助设计,而且一般立足于不同的设计规程和模型化工具,如关系数据库 模式的辅助设计工具的应用。许多自动化工具,如 Oracle Designer,已经具有如下一些稳定的特性:
- 确定业务和用户需求的功能;
- 对业务处理建模的功能;
- 对数据流建模的功能;
- 对实体机器相互关系建模的功能;
- 生成创建数据库对象的 DDL 语句的功能;
- 对数据库设计周期的支持;
- 业务处理二次工程;
- 数据库和应用软件的版本控制;
- 文档和用户反馈信息报告的生成。
敏捷数据库设计方法
今年来,一种新的软件开发方法学—敏捷方法学呗逐步应用于数据库设计。它提出了在可控制方式下的进化设计。迭代式开发是它的一个重要特点,即整个项目生命周期 中运行多个完整的软件生命周期循环。敏捷过程在每次迭代中都会度过一个完整的生命周期且迭代时间较短。
敏捷方法的一些原则包括:
- 拥有不同技能和背景的人能够紧密合作;
- 每个项目组成员都有自己的数据库实例;
- 开发人员的数据库经常集成到共享主数据库;
- 数据库包含计划和测试数据;
- 所有的变化要求数据库重构;
- 每个数据库重构都可以通过编写 SQL DDL(对于计划变化)和 DML(对于数据迁移)来自动完成;
- 自动地更新所有开发人员的数据库;
- 清晰地分离所有的数据库获取代码等。
敏捷数据库设计方法保持多个数据库在一个系统中,而且不需要专职的 DBA。可以通过开发一些简单工具帮助解决数据库进化过程中大量的重复性工作。
目前,敏捷方法在数据库设计中的应用尚有一些没有解决的问题,如集成数据库和 24X7 小时实施等,还有待进行进一步的研究工作。
此外,其他的设计方法还有属性分析法、实体分析法及基于抽象语义规范的设计法等。在实际的设计过程中,各种方法可以结合起来使用,例如,在基于视图概念的设计方法 中可用 E-R 方法来表示各个视图。
数据库设计的基本步骤
按照规范设计的方法,考虑数据库及其应用系统开发全过程,将数据库设计分为以下 6 个阶段(如图):
- 需求分析;
- 概念结构设计;
- 逻辑结构设计;
- 物理结构设计;
- 数据库实施;
- 数据库运行和维护。
在数据库设计过程中,需求分析和概念设计可以独立于任何数据库管理系统进行。逻辑设计和物理设计与选用的 DBMS 密切相关。
数据库设计开始之前,首先必须选定参加设计的人员,包括系统分析人员、数据库设计人员、应用开发人员、数据库管理员和用户代表。系统分析
和数据库设计人员
是数据库设计的核心人员,他们将自始至终参与数据库设计,他们的水平决定了数据库系统的质量。用户
和数据管理员
在数据库设计中举足轻重的,他们主要参加
需求分析和数据库的运行与维护,他们的积极参与(不仅仅是配合)不但能加速数据库设计,而且也是决定数据库设计质量的重要因素。应用开发人员
(包括程序员
和操作员)分别负责编制程序和准备软硬件环境,他们在系统实施阶段参与进来。
如果所设计的数据库应用系统比较复杂,还应该考虑是否需要使用数据库设计工具以及选用何种工具,以提高数据库设计质量并减少设计工作量。
分步设计法:
分步设计法遵循自顶向下、逐步求精的原则,将数据库设计过程分解为若干相互独立又相互依存的阶段,每一阶段采用不同的技术与工具,解决不同的问题,从而将问题 局部化,减少了局部问题对整体设计的影响。目前,此方法已在数据库设计中得到了广泛应用并获得了较好的效果。
在分步设计法中,通常将数据库的设计分为需求分析
、概念结构设计
、逻辑结构设计
和数据库物理设计
四个阶段。在数据库设计的整个过程中,
需求分析和概念设计可以独立于任何的数据库管理系统(DBMS),而逻辑设计和物理设计则与具体的数据库管理系统密切相关。
需求分析阶段
进行数据库设计首先必须准确了解与分析用户需求(包括数据与处理)。需求分析师整个设计过程的基础,是最困难、最耗费时间的异步。作为“地基”的需求分析是否 做得充分与准确,决定了在其上构建数据库大厦的速度与质量。需求分析做得不好,甚至会导致整个数据库设计返工重做。
需求分析说明书:
需求分析
是指收集和分析用户对系统的信息需求和处理需求,得到设计系统所必需的需求信息,建立系统说明文档。其目标通过调查研究,了解用户的数据要求和
处理要求,并按一定格式整理形成需求说明书
。需求说明书是需求分析阶段的成果,也是今后的设计的依据。它包括数据库锁涉及的数据、数据的热证、使用频率和
数据量的估计,如数据名、属性及其类型、主关键字属性、保密要求、完整性约束条件、更改要求、使用频率、数据量估计等。这些关于数据的数据称为元数据
。
在设计大型数据库时,这些数据通常由数据字典
来管理。用数据字典管理元数据有利于避免数据的重复或重名以保持数据的一致性及提供各种统计数据,因而有利于
提高数据库设计的质量,同时可以减轻设计者的负担。
需求分析的目标:
需求分析的目标是给出应用领域中数据项、数据项之间的关系和数据操作任务的详细定义,为数据库的概念设计、逻辑设计和物理设计奠定基础,为优化数据库的逻辑结构 和物理结构提供可靠依据。设计人员应与用户密切合作,用户则应积极参与,从而使设计人员对用户需求全面、准确的理解。
概念结构设计阶段
概念结构设计
是数据库设计的第二阶段,是整个数据库设计的关键,它通过对用户需求进行综合、归纳与抽象,形成一个独立于具体 DBMS 的概念模型。
概念结构设计的目标:
概念结构设计目标是对需求说明书
提供的所有数据和处理哟求进行抽象与综合处理,按一定的方法构造反映用户环境的数据及其相互联系的概念模型
,即用户
的数据模型或企业的数据模型。
概念数据模型:
这种概念数据模型与 DBMS 无关,是面向现实世界的、极易为用户所理解的数据模型。为保证所设计的概念数据模型的正确,完全地反映用户的数据及其相互关系,便于进行 所要求的各种处理,在本阶段设计中刻吸收用户参与和评议设计,从而有利于保证数据库的设计与用户的需求相吻合。该模型是准确描述应用领域的信息模式, 支持用户的各种应用,这样既容易转换为数据库逻辑模式,又容易为用户理解。数据库概念模式是独立于任何数据库管理系统,面向现实世界的数据模型, 不能直接用于数据库的实现。但是,这种模式易于为用户理解,而且涉及人员可以致力于模拟现实世界,而不必过早地纠缠于 DBMS 锁规定的各种细节。
在进行概念结构设计时,可先设计各个应用的视图,即各个应用所看到的数据及其结构,然后再进行视图集成,以形成一个单一的概念数据模型。这样形成的初步数据模型 还要经过数据库设计者和用户的审查与修改,最后形成所需的概念数据模型。
逻辑结构设计阶段
在逻辑设计阶段,将第二阶段锁得到的数据库概念模式
,转换成以 DBMS 的逻辑数据模型表示的```逻辑模式``,同时将概念设计阶段得到的应用视图转换成外部模式`
即特定 DBMS 下的应用视图。
数据库逻辑设计的目标
是:进一步落实需求说明,并满足用户的完整性和安全性要求,能在逻辑级上高效率地支持各种数据库事务的运行。
数据库的逻辑设计不仅涉及数据模型的转换问题,而且涉及进一步深入解决数据模式设计中一些技术问题,例如数据模式的规范化、满足 DBMS 各种限制等。
数据库逻辑设计的结果以数据定义语言(DDL)
表示。由于 SQL 语言是综合性语言,DDL 就相当于 SQL 中的定义关系模式部分。
物理设计阶段
物理设计是为逻辑数据模型选取一个最适合应用环境的物理结构
(包括存储结构和存取方法)。物理设计阶段的任务是把逻辑设计阶段得到的满足用户需求的已确定
的逻辑模型在物理上加以实现,其主要的内容是根据 DBMS 提供的各种手段,设计数据的存储形式和存取路径,如文件结构、索引的设计等,即设计数据库的内模式或存储
模式。数据库的内模式对数据库的性能影响很大,应根据处理需求及 DBMS、操作系统和硬件的性能进行精心设计。
实际上,数据库设计的基本过程与任何复杂系统开发一样,在每一阶段设计基本完成后,都要进行认真的检查,看看是否满足应用需求,是否符合前面已执行步骤的要求和 满足后续步骤的需要,并分析设计结果的合理性。在每一步设计中,都可能发现前面步骤的遗漏或处理的不当之处,此时,往往需要返回去重新处理并修改设计和有关文档。 所以,数据库设计过程通常是一个反复修改、反复设计的迭代过程。
数据库实施阶段
在数据库实施阶段,设计人员运用 DBMS 提供的数据库语言(如 SQL)及其宿主语言,根据逻辑设计和物理设计的结果建立数据库,编制与调试应用程序,组织数据入库, 并进行试运行。
数据库运行和维护阶段
数据库应用系统经过试运行后即可投入正式运行。在数据库系统运行过程中必须不断地对其进行评价、调整与修改。
小结:
设计一个完善的数据库应用系统是不可能一蹴而就的,它往往是上述 6 个阶段的不断反复。
需要指出的是,这个设计步骤既是数据库设计的过程,也包括了数据库应用系统的设计过程。在设计过程中把数据库的设计和对数据库中数据处理的设计紧密结合起来。将 这两个方面的需求分析、抽象、设计、实现在各个阶段同时进行,相互参照,相互补充,以完善两方面的设计。事实上,如果不了解应用环境对数据的处理要求,或没有 考虑如何去实现这些处理要求,是不可能设计一个良好的数据库结构的。按照这个原则,设计过程各个阶段的设计描述,可用下图概括地给出。
图中的有关处理特性的设计描述中,其设计原理、采用的设计方法、工具等在软件工程和信息系统设计的课程中有详细介绍,这里不再讨论。
数据库设计过程中的各级模式
按照上一节的设计过程,数据库设计的不同阶段形成数据库的各级模式,如下图所示。
- 需求分析阶段,综合各个用户的应用需求;
- 在概念设计阶段形成独立于机器特点,独立于各个 DBMS 产品的概念模式,可以使用 E-R 图;
- 在逻辑设计阶段将 E-R 图转换成具体的数据库产品支持的数据模型,如关系模型,形成数据库逻辑模式;然后根据用户处理的要求、安全性的考虑, 在基本表的基础上再建立必要的视图,形成数据的外模式;
- 在物理设计阶段,根据 DBMS 特点和处理的需要,进行物理存储安排,建立索引,形成数据库内模式。
需求分析
需求分析是数据库设计过程的第一步,是整个数据库设计的依据和基础。需求分析做得不好,就会导致整个数据库设计重新返工。
需求分析的任务
需求分析的任务是通过详细调查现实世界要处理的对象(组织、部门、企业等),充分了解原系统(手工系统或计算机系统)工作概况,明确用户的各种需求,然后在此基础上 确定新系统的功能。新系统必须充分考虑今后可能的扩充和改变,不能仅仅按当前用用需求来设计数据库。
需求分析人员既要对数据库技术有一定的了解,又要对单位的情况比较熟悉,一般由数据库人员和本单位的有关工作人员合作进行。需求分析的结果整理成需求设计说明书
,
这是数据库技术人员和应用单位的工作人员取得共识的基础,必须得到单位有关管理人员的确认。
目前,需求分析说明书一般用自然的语言表达,是非形式化的。在需求分析说明书中,已经确认了数据库中应包含的数据及其有关的特性,例如数据名、属性及其类型、键码、
使用频率、更新要求、数据量估计、保密要求、共享范围以及语义约束等。这些数据是关于数据的数据,即元数据
。在设计大型数据库时,用人工管理这些元数据是
困难的,也不便于查询和使用。一般用专用软件包或 DBMS 来管理这些数据,称为数据字典
。数据字典不同于数据目录:
数据目录
主要是面向系统的,它是 DBMS 的一个组成部分;数据字典
是面向数据库实现人员和用户的,它是用 DBMS 或专用软件实现的一个应用系统。
用数据字典管理元数据,不但可以减少设计者的负担,也有利于保持数据的一致性(例如避免重复或重名)并可提供各种统计数据,因而可以提高数据库设计的质量。为了 便于在后续阶段用计算机处理需求说明,需求说明有时转换成形式化和半形式化的描述形式,例如需求描述语言、框图、信息流图等。但是数据库的需求是多方面的, 数据的语义是丰富多彩的,要完全形式化描述数据库设计的需求说明,至少在目前还难以做到,还得辅以非形式化的说明。
确定用户的最终需求是一件很困难的事,这是因为:
- 一方面用户缺少计算机知识,开始时无法确定计算机究竟能为自己做什么、不能做什么,因此往往不能准确地表达自己的需求,所提出的需求往往不断地变化。
- 另一方面,设计人员缺少用户的专业知识,不易理解用户的真正需求,甚至误解用户的需求。因此设计人员必须不断深入地与用户交流,才能逐步确定用户的实际需求。
一般需求分析分为应用领域的调查、定义数据库支持的信息与应用、定义数据库操作任务、定义数据字典、预测未来的改变等几步。
需求分析几个步骤:
应用领域的调查
应用领域的调查分为两个阶段:
- 对应用领域的组织结构、业务流程和数据流程进行调查,对现行系统的功能和所需信息有一个明确的认识;
- 在第一阶段的基础上进行应用领域的分析,抽象应用领域的逻辑模型,最后把逻辑模型用数据流图来表示。
数据流图
可以表示现行系统的信息流动和加工处理等详细情况,是现行系统的一种逻辑抽象表示,它独立于系统的实现。下表是数据流图使用的符号及其说明:
调查的重点是“数据”和“处理”,通过调查、收集与分析,或得用户对数据库如下要求:
- 信息要求:
信息要求
是指用户需要从数据库中获得信息的内容与性质。由信息要求可以导出数据要求,即在数据库中需要存储哪些数据。
- 处理要求:
处理要求
是指用户要完成什么处理功能,对处理的响应时间有什么要求,处理方式是批处理还是联机处理。
- 安全性与完整性要求。
定义信息与应用
定义数据库系统支持的信息的目的是确定最终数据库需要存储哪些信息。信息定义应用领域的逻辑模型为基础。信息定义分为以下两步:
(1)考察数据流图中每个存储信息,确定其是否应该而且可能由数据库存储,如果应该而且可能,则列入数据库需要存储的信息范围。
(2)对于上面产生的每个需要由数据库存储的信息,进行严格定义,内容包括:信息名、内容定义、产生该信息的应用和引用该信息的应用。信息定义集合可用表 7.2(a) 的 形式表示。例如图 7.3 中的“统计结果”需要由数据库存储,则其信息定义集合表示为表 7.2(b)。
定义数据库系统支持的应用的目的是确定最终的数据库支持哪些应用系统。由应用领域调查所产生的逻辑模型是定义数据库系统支持的应用的基础。利用这个逻辑模型, 按照下列步骤来完成应用的定义:
(1)考察数据流图中的每个数据处理应用,确定正在设计的数据库是否应该而且可能支持这个应用。如果应该而且可能支持,即把这个功能列入数据库系统支持的应用范围。
(2)对于上面产生的每个数据库系统应该支持的应用,进行严格的定义,内容包括应用名、处理功能、输入信息和输出信息。数据库应用定义集合可以用表 7.3(a)的 形式表示。例如图 7.3 中的“统计处理”应用,可以用表 7.3(b) 来表示。
定义操作任务
数据库操作任务对应于最终数据库系统的事务
。一个应用包括一个或多个数据库操作任务。每个数据库操作任务可属于多个应用。数据库操作任务的定义
是
对应用定义集合中每个应用逐步求精的过程。在逐步求精的过程中,划分出数据库操作任务,完成数据库操作任务的定义。划分数据库操作任务的规则如下:
- 每个数据库操作任务必须是某个应用的组成部分;
- 每个数据库操作任务必须是一个独立的计算机执行单位,具有相对独立的功能;
- 每个数据库操作任务内的所有数据库操作必须具有
原子性
,即当该任务成功地运行结束时,所有操作对数据库的影响必须同时存在;当任务失败时,所有操作对 数据库的影响必须全部清除。 - 每个数据库操作任务必须具有明确的输入和输出数据项集合定义,每个数据项必须是详细说明的原子数据项。
根据上述规则,我们可以对应用定义结合中的每个应用进行逐步求精,得到一个数据库操作任务集合。然后,我们对每个操作任务进行定义,定义的内容如下:
然后,用图表的方式来表示每个数据库操纵任务的定义,这种图表称为数据库输入处理输出图
,简称为 DBIPO 图
。
定义数据项
数据项的定义是数据库设计的最基本而且最重要的工作。数据项定义以数据库操作任务定义为基础,详细过程如下:
- 从 DBIPO 图中提取出所有原子数据项;
- 把有联系的数据项组合起来形成数据组;
- 以数据组为单位,写出数据项的如下定义:
- 语义定义:名字、实际意义等;
- 完整性约束定义:数据类型、数据长度、小数位数、值约束、空值约束以及其他比较复杂的完整性约束等。
- 根据用户和实际领域的信息模型需要补充其他数据项及其定义;
- 形成数据定义字典,包括上面数据项定义的所有内容。
预测未来的改变
预测现行系统的未来改变是为了使数据库具有较高的适应性。现行系统的未来改变信息是其他数据库设计阶段的参考信息。使用这些信息,我们可以始终考虑如何使最终 数据库尽量适应未来变化,减少将来为适应改变而引起的数据库修改或重新设计。现行系统未来改变的预测需要与用户进行讨论,讨论的内容一般包括以下几个方面:
- 应用领域中已有的,但数据库系统目前尚未支持的应用;
- 应用领域中各种应用功能的可能扩充、减少和改变;
- 应用领域的上述改变对数据库支持的信息和应用范围、数据项定义、数据项之间的联系和数据操作任务的影响。
然后,根据上面的讨论的结果形成现行系统未来改变预测的说明书。
实体联系(ER)模型
实体联系模型简称为ER 模型
。实体
是 ER 模型的基本对象。
实体和属性
实体
是 ER 模型的基本对象。实体是现实世界中各种事物的抽象。实体是可以物理存在的事物,也可以是抽象的概念。每个实体都有一组特征或性质,
称为实体的属性
。实体属性的一组特定值确定了一个特定的实体。实体的属性值是数据库存储的主要数据。
某些属性可以划分为多个具有独立意义的子属性。例如,地址属性可以划分为邮政编码、省份等子属性,这类属性称为复合属性
。复合属性具有层次结构,如下图:
复合属性的用途:
- 准确模拟现实世界的符合信息结构;
- 当用户既需要把符合属性作为一个整体使用也需要单独使用各子属性时,属性的符合结构十分重要。
多数实体属性多数单值属性
,即对于同一实体只能取一个值,如人的年龄。在某些情况下,实体的一些属性可能取多个值,这样的属性称为多值属性
,例如
有的人具有多个学位。
实体属性之间可能具有某种关系,如人的年龄和生日属性具有相互依赖关系。从当前日期和生日属性的值可以确定年龄属性的值,即年龄属性的值可以由其他属性导出,
这样的属性称为导出属性
。导出属性的值不仅可以从另外的属性导出,也可以从有关的其他实体中导出,比如,一个公司实体的雇员数属性的值可以通过累积该
公司所有雇员数得到。实体的有些属性可能没有适当值可设置,这些属性通常被设置一个称为空值
的特征值。
实体型、键属性和属性的值域
实体型
一个数据库通常存储很多类似的实体,例如大学中老师很多,属性是类似的,但具体到每个老师的属性值大多是不同的。这些类似的实体抽象为一个实体型
。
实体型是一个具有相同属性的实体集合,由一个实体型和一组属性来定义。实体型的定义称为实体模式
,描述了一组实体的公共信息结构。实体型所表示的实体
集合中的任一实体称为该实体型的实例
,简称实体
。在任意时刻,一个实体型的所有实体的集合称为该实体型的外延
。同一个实体型的不同实体是
现实世界中不同的对象。
键
在 ER 模型中每个实体型具有一个由一个或多个属性组成的键
,用来区别不同的实体。对于同一个实体型的不同实体,键的值必须相异。比如,大学的名字属性是键。
由一个属性构成的键称为简单键
。由多个属性构成的键称为复合键
。
键是实体型的一个重要完整性约束,规定了不同的实体在键上不能取相同的值。一个实体型可以具有多个键。
实体型的每个简单属性都具有一个值域
,说明这个属性的可能取值范围。
数据库实例
实体间的联系
一个数据库通常都包含很多实体型。不同实体型的实体之间可能具有某种联系,这种联系称为实体间的联系
。例如,在大学数据库中,一个教研室必属于一个系,
一个学生必属于一个系等。
联系型和联系实例
联系型的结构约束
联系型通常都具有结构约束。结构约束分为两类:实体对应约束
和实体关联约束
。一个联系型的实体对应约束规定了该联系型锁关联的实体间的对应关系。
实体对应约束包括三种:一对一约束、一对多约束、多对多约束。
实体对应约束:
实体关联约束:
联系型的属性
弱实体
实际领域中经常存在一些实体型,没有自己的键盘,这样的实体型称为弱实体想
。弱实体型的实体称为弱实体
。弱实体型的不同实体的属性值可能完全相同,
难以区别。为了区别弱实体,弱实体型需要与一般实体型相关联。
设联系型 R 关联弱实体型 A 和一般实体型 B。弱实体型 A 的不同实体可以通过与 B 的有关实体相结合来加以区别。B 称为实体型 A 的识别实体型
。R 称为弱
实体型 A 的识别联系
。识别联系型对于弱实体型必须具有全域关联约束
。一个弱实体型可以具有多个识别实体型和多个识别联系。
弱实体型必须具有一个或多个属性,使得这些属性可以与识别实体型的键相结合形成相应弱实体型的键,这样的弱实体属性称为弱实体型的部分键
。给定一个弱
实体型,我们可以使用它的识别实体型的键和它的部分键识别不同的弱实体。例如,在上边的例子中,孩子名是弱实体型孩子的部分键。
实体联系图(ER 图)
扩展的实体联系模型
扩展的实体联系模型是 ER 模型的扩充,简称 EER 模型。EER 模型
包括了 ER 模型的所有概念。此外,它还包括子类、超类、演绎、归纳、范畴、属性层次等
概念。
子类、超类、演绎和归纳
子类和超类
演绎
归纳
演绎和归纳的性质
由属性谓词定义的子类:
演绎和归纳的约束条件:
多层演绎和共享子类:
范畴与范畴化
EER 图
概念数据库设计
概念数据库设计又称为概念结构设计
,其任务包括两个方面:概念数据库模式设计
和事务设计
。
- 概念数据库模式设计任务:
概念数据库模式设计
的任务是以需求分析阶段所识别的数据项和应用领域的未来改变信息位基础,使用高级数据模型建立概念数据库模式。
- 事务设计的任务:
事务设计
的任务是考察需求分析阶段提出的数据库操作任务,形成数据库事务的高级说明。
概念数据库模式设计概述
概念数据库模式设计
的任务是以需求分析阶段所识别的数据项和应用领域的未来改变信息位基础,使用高级数据模型建立概念数据库模式。
概念数据库模式设计目标:
- 准确描述应用领域的信息模式,支持用户的各种应用;
- 既易于转换为逻辑数据库模式,又容易为用户理解。
概念数据库模式独立于任何数据库管理系统,不能直接用于数据库的实现。但是这种独立性
是非常重要的,其原因如下:
(1)概念数据库模式设计的过程是彻底理解应用领域的信息结构、语义、信息的相互联系和各种约束的过程。这个过程应该独立于任何数据库管理系统。不然,特定数据 库管理系统的局限性将给概念设计带来不应有的影响。
(2)概念数据库模式是数据库内容的静态描述
。尽量当选择不同的数据库管理系统或改变逻辑与物理设计阶段的设计决策时,不需要改变概念数据模式。
(3)概念数据库模式的正确理解对于用户和应用程序设计者是非常关键的。独立于数据库管理系统的高级数据模型比特定的数据库管理系统的数据模型更一般化,具有 更强的表达能力。使用这种数据模型进行概念设计能有助于正确理解概念数据库模式。
(4)用图形方式
表示的概念数据库模式直观易懂,有利于数据库设计者、用户和系统分析员之间的信息交流。高级数据模型通常都具有图形表达能力。
概念数据模型的特点:
在概念设计阶段一般都适用语义数据模型
或概念数据模型
。这类数据模型具有如下特点:
- 具有很强的表达能力,能够方便地表达各种类型的数据、数据间的联系和各种约束;
- 简单易懂,概念清晰,容易适用;
- 组成模型的概念少,概念定义严格,无多义性,不同概念的语义不重叠;
- 具有适用图形表示概念模式的能力。
有很多可用于概念数据库设计的高级数据模型,比较流行的有实体联系模型
和扩展的实体联系模型
。
概念数据模型的作用:
- 提供能够识别和理解系统要求的框架;
- 为数据库提供一个说明性结构,作为设计数据库逻辑结构即逻辑模型的基础。
数据结构设计的策略主要有:自底向上、自顶向下、有里向外和混合策略。
概念设计的基本方法
要进行数据库的概念设计,首先必须选择适当的数据模型。用于概念设计的数据模型要具有如下的特点:
- 有足够的表达能力,可以很方便地表示各种类型的数据及其相互间的联系和约束;
- 简明易懂,容易适用,能为非计算机专业人员所接受;
- 组成模型的概念少,定义严格,无多义性;
- 具有适用图形表示概念模式的能力。
目前有很多可供选择的高级数据模型,例如各种语义数据模型,面向对象数据模型等。应用得最广泛的是实体-联系(E-R)模型。ER 模型除了具有上述的特点外,还可以 用 ER 图表示数据模式,便于理解与交流。
用 ER 模型设计数据模式,首先必须根据需求分析说明书
,确认实体集、联系和属性。实体集、联系和属性的划分不是绝对的。实体集本来是一个无所不包的概念,
属性和联系都可以看成是实体集。引入属性和联系的概念,是为了更清晰、明确地表示现实世界中各种食物彼此之间的联系。概念设计所产生的模式要求比较自然地反映
现实世界。因此,实体集、属性和联系的划分实质上反映了数据库设计者和用户对现实世界的理解和观察。它既是对客观世界的描述,又反映出设计者的观点甚至偏爱。
所以对于同一个单位,不同的设计者会设计出不同的数据模式。
数据库概念设计方法主要有两种,一种是集中式设计方法
,另一种是视图综合设计方法
。
集中式模式设计法
在这种方式中,首先将需求说明综合成一个统一的需求说明,即合并在需求分析阶段得到的各种应用的需求, 一般由一个权威组织或授权的数据库管理员 DBS 进行此项综合工作。然后,在此基础上设计一个单位的全局数据模式,以满足所有应用的要求。 再根据全局数据模式为各个用户组或应用定义数据库逻辑设计模式。
这种方法强调统一,对各用户组合应用可能照顾不够,一般用于小的、不太复杂的单位。如果一个单位很大、很复杂,综合需求说明是很困难的工作。而且在综合过程中, 难免要牺牲某些用户的要求。
视图综合设计法
视图综合设计法不要求综合成一个统一的需求说明,而是以各部分的需求说明为基础,分别设计各自的局部模式。这些局部模式实际上相当于各部分的视图,然后再以 这些视图为基础,集成为一个全局模式。在视图集成过程中,可能会发现一些冲突,须对视图做适当的修改。由于集成和修改是 ER 模型表示的模式上进行,一般可用 计算机辅助设计工具来进行,修改后的视图可以作为逻辑设计的基础。
两种方法的比较:
从表面上看,集中式模式设计法修改的是局部需求说明,而视图综合设计法修改的是视图,两者似乎无多大差别。但两者的设计思想是有区别的;视图集成法
是以局部需求说明作为设计的基础,在集成时尽管对视图要做必要的修改,但视图是设计的基础,全局模式
是视图的集成;集中式模式设计法
是在同一需求
说明的基础上,设计全局模式,在设计数据库逻辑模式,全局模式是设计的基础。
这两种方法的不同仅在于应用需求合成的方式与阶段不同、
视图继承法比较适合于大型数据库的设计,可以多组并行进行,可以免除综合需求说明的麻烦。
概念设计的策略
给定一组需求说明,概念设计的任务是建立一个满足给定需求的概念数据库模式。目前存在很多种完成这项任务的策略。多数策略遵循逐步求解的原则,即一个满足某些 需求的简单模式开始,逐步加以完善,最后形成满足所有需求的概念数据库模式。
- 自顶向下的策略:
从一个包含高级抽象概念结构的模式触发,对这些高级抽象概念结构逐步求精,形成最终的概念数据库模式。例如,我们可以首先建立一个包含介个较高级实体型的模式, 然后逐步把它们分解为低级的实体型和联系型,把一个实体型分解为子类的演绎过程是一个自顶向下的设计策略。
即首先定义全局概念结构的框架,然后逐步细化,如下图所示:
- 自底向上的策略
从包含基本概念结构的模式触发,逐步组合这些基本概念结构,形成最终的概念数据库模式。例如,我们可以首先说明属性,然后分组这些属性,形成实体型和联系型。 前面介绍的由子类形成超类的归纳过程就是一个自底向上的设计策略。
即首先定义各局部应用的概念结构,然后将它们集成起来,得到全局概念结构,如下图所示:
它通常分为两步:第一步是抽象数据并设计局部视图
;第二步是集成局部视图,得到全局的概念结构。
- 逐步扩张策略
首先定义最重要的黑心概念结构,然后向外扩充,以滚雪球的方式逐步生成其他概念结构,直至总体概念结构,如下图所示:
- 混合策略:
首先使用自顶向下的策略把应用需求划分为多个需求子集合;然后,对于每个需求子集合,使用自底向上的策略设计局部模式;最后,组合局部模式, 形成最后的概念数据库模式。
即将自顶向下和自底向上相结合,用自顶向下策略设计一个全局概念结构的框架,以它为骨架集成由自底向上策略中设计的各局部概念结构。
数据抽象
概念结构是对现实世界的一种抽象。所谓抽象
是对实际的人、物、事和概念进行人为处理,抽取所关心的共同特性,负略非本质的细节,并把这些特性用各种概念
精确地加以描述,这些概念组成了某种模型。
一般有三种抽象:
- 分类:
定义某一类概念作为现实世界中一组对象的类型,这些对象具有某些共同的特性和行为。它抽象了对象值和型之间的“is member of”的语义。在 ER 模型中,实体型就是 这种抽象。
- 聚集:
定义某一类型的组成成分。它抽象了对象内部类型和成分之间“is part of”的语义。在 ER 模型中若干属性的聚集组成了实体型,就是这种抽象,如下图所示:
更复杂的聚集如下图,即某一类型的成分仍是一个聚集。
- 概括:
定义类型之间的一种子集联系。它抽象了类型之间“is subset of”的语义。例如,学生是一个实体型,本科生、研究生也是实体型。本科生、研究生均是学生的子集。
把学生成为超类
,本科生、研究生成为学生的子类
。
扩展 ER 模型支持概况,允许定义超类实体型和子类实体型,并用竖边的矩形框表示子类,用直线加小圆圈表示超类-子类的联系。
概括有一个很重要的性质:继承性。子类继承了学生类型的属性。当然,子类可以增加自己的某些特殊属性。
概念结构设计的第一步就是利用上面介绍的抽象机制对需求分析阶段收集到数据进行分析、组织(聚集),形成实体、实体的属性,标识实体的码,确定实体之间的联系 类型(1:1,1:n,m:n)。
局部视图设计
局部概念模式(试图)可以由用户独立完成,也可以由数据库设计者协助完成。
试图设计的任务
- 第一项任务
根据局部需求分析的结果使用适当的概念设计策略,产生局部实体。局部实体
应该是局部应用领域中的对象,能够满足局部应用的需求。局部实体的差生包括确定
局部实体的属性和键。
在局部概念模式设计过程中,我们可能遇到这样一些对象:它们既可以抽象为实体也可以抽象为属性或实体间联系。对于这样的对象,我们应该使用最易于用户理解的 概念模型结构来表示。需要注意的是,每个对象必须由一种而且及仅由一种概念模型结构表示。在设计局部实体时,我们还需要确定哪些属性是单值属性、哪些是多值 属性、哪些是导出属性和哪些是复合属性。
- 第二项任务:
局部概念设计的第二项任务是根据局部需求分析的结果确定局部实体间的联系及其结构约束。局部实体间的联系要准确地描述局部应用领域中各对象之间的关系。同时, 局部实体间的联系也要满足局部应用的各种要求。
- 第三项任务:
深入分析局部实体之间的关系,应用演绎或归纳过程,确定局部实体间的超类/子类来袭、共享子类和范畴。同时,还需要确定他们的正交和完全性约束。
视图设计步骤
在实体分析法中,局部视图设计的第一步是确定其所属的范围,即它所对应的用户组,然后对每个用户组建立一个仅由实体、联系及它们的标识码组成的局部信息结构 (局部数据模式)框架,最后再加入有关的描述信息,形成完整的局部视图(局部数据模式)。这样做的目的是为了集中精力处理好用户数据需求的主要方面,避免 因无关紧要的描述细节而影响局部信息结构的正确性。整个过程可分为以下几个步骤:
- 确定局部视图的范围;
- 识别实体及其标识;
- 确定实体间的联系;
- 分配实体及联系的属性。
确定局部视图的范围
需求说明书中标明的用户视图范围可以作为确定局部视图的基本依据,但它通常与子模式范围相对应,有时因为过大而不利于局部信息结构的构造,故可根据情况修改, 但也不宜分得过小,过小会造成局部视图的数量太大及大量的数据冗余和不一致性。给以后的视图集成带来很大的困难。
局部视图范围确定的基本原则是:
- 各个局部视图支持的功能域之间的联系应最少;
- 实体个数矢量:
一个局部视图所包含的实体数量反映了该局部视图的复杂性,按照信息论中“7±2”观点,人们在同一时刻可同时顾及的事情一般在 5~9 之间,以 6 或 7 最为适当。 因此,一个局部视图内的实体数不宜超过 9 个,否则就会过于复杂,不便于人们理解和管理。
识别实体及其标识
在需求分析中,人们已经初步地识别了各类实体、实体间的联系及描述其性质的数据元素,这些统称为数据对象
,它们是进一步设计的基本素材。这一步的任务就是
在确定的视图范围内,识别哪些数据对象作为局部视图的基本实体及其标识,并定义有关数据对象在 ER 模型中的地位。
数据对象的分类:
为了确定数据对象在局部 ER 数据模型中的地位,首先必须对所有已识别的数据对象加以适当的分类,以便于根据它们所属的对象类来确定它们在相应局部 ER 模型中的
身份。数据对象分类的原则
是同一类中的对象在概念上应该具有共性。例如,高校中的教师这个概念是指在职的教学人员,因此,教授、副教授、讲师和助教均可
归入教师这一类,但他们在概念上并不完全相同,除了共享之外,还各有其特殊之处,如教授、副教授有研究方向、知道研究生等描述项,他们的职称也不一样。因此数据
对象存在分类层次
问题,谓词可运用面向对象数据模型中子类与超类的概念。
识别实体与属性:
建立局部 E-R 数据模型,还须识别每个对象类在局部 E-R 模型中的地位:实体
、属性
或联系
。实体和属性之间在形式上的界限并不明显,常常是
现实世界对它们已有的大体的自然区分,随应用环境的不同而不同。在给定的应用环境中区分实体和属性的总的原则是:要在此应用环境中显得合理,且同一个对象在
同一局部视图内只能做一种成分,不能既是实体又是属性。此外,为了对已给定的需求目标,更合理地确认局部 E-R 模型中的实体和属性,以便在逻辑设计阶段从 E-R 模型
得到更接近于规范的关系模式,可按下述一般规则来区分实体与属性:
- 描述信息原则:
在 E-R 模型中的实体均有描述信息,而属性则没有。据此,可将一个需要描述信息的对象类作为实体,而将只需有一个标识的对象类归为属性。例如,仓库这个对象 类在某些事务处理中需要用到仓库的面积、地点、管理员姓名等描述信息,则宜将其归入实体。但如人的年龄、物品的重量等对象类,在一般应用中都不需要描述信息, 所以他们在通常情况下都作为属性。
- 多值性原则:
所谓多值性
是指若一个描述项存在多个值描述其描述对象,则即使该描述项本身没有描述信息也应化为实体。例如加工种类与其描述的工件之间就符合多值性原则,
因为每个工件实体可能需要多个工种的加工,尽管工种除了工种名外不需要其他的描述,但还是讲工种作为实体为好。
需要注意的是,这一原则最好与存在性原则结合起来使用,如果将被描述对象删除后,描述项没有再存在的意义,则即使此描述项是多值得也不宜作为实体。例如零件的 颜色可以是多值得,但颜色离开了其描述的对象就没有单独存在的意义,因此还是作为属性为宜。
- 存在性原则:
- 多对一联系性:
属性不再与其描述对象以外的其他对象类发生联系。相反,如果一个对象的某个描述项与另一个对象类存在着多对一联系,则此描述项即使本身没有描述信息,也应将 其作为实体。例如在前面所讲的工件与加工种类的例子中,如果还有一个车间实体,且加工种类与车间之间存在多对一的联系,则将加工种类华为实体更合理。
- 组合标识判别原则:
若一个对象类的标识是由其他对象类的标识组成的,该对象一般应定义为联系。相反,如果组成某对象类标识的各成分不是其他实体的标识,且作为实体在应用的上下 关系中很自然,则可以定义为实体。例如,一个工厂生产的零件须由名称及规格组成组合标识,在一般应用中应将零件作为实体较为适宜。
实体与属性的识别过程是个相互作用的反复过程,随着实体的确认,属性也将趋于明朗,反之亦然。在此过程中根据应用需求对已经识别的实体和属性做适当指派,发现 问题再来调整,在标识过程中必须遵循前面所讲的总原则。
对象的命名:
在需求分析中得到的数据对象通常都是有名称的,但由于这些名称未经规范化,常常存在诸如同名异义、异名同义等许多命名上的冲突、不一致性及语义不清等问题, 是造成数据不一致性及数据冗余的一个重要原因。此外,数据对象原有的名称有的过于冗长,给使用带来很大不便。谓词,需要按一定的规范对每一类数据对象重新命名, 给它制定一个简洁明了且唯一的名字,避免异名同义和异义同名存在。命名规范一般包含以下原则和规定:
- 数据对象名应清晰明了便于记忆,并尽可能采用用户熟悉的名字;
- 名字要反映数据对象的主要特点并力求简洁,以利于减少冲突和方便使用;
- 遵守缩写规则。缩写规则包括一般缩写规则和系统中专用名称的缩写规定,对于较大的复杂系统应编制缩写字典,便于参照。凡有缩写规定的不得使用全称,以免混淆。
- 规定统一的命名约定并加以遵守。例如对属性的命名可以采用如下形式的约定:实体名·分类词—修饰词
其中,分类词指单位内通用的数据项名,如名称、号码、小计、总计、合计、单位等。每个单位应有一个标准的分类词表,加于分类前面的实体名和后面的修饰词可用以 说明该分类词在特定的上下文中具有的特殊含义。例如,合同上的数据项日期可命名为:合同·日期—年月
指定命名约定的基本原则是简明一致、避免混淆,具体可根据单位内数据对象的复杂程度自行制定。
在完成了实体与属性的识别后,必须按照命名规范仔细地审核没类数据对象的名字,纠正不符合规范的命名,务必使每个对象名符合规范要求。
确定实体的标识:
实体的标识能够唯一地标识一个实体的属性或属性组,也就是该实体的关键字。确定实体标识在实体识别与规范化命名之后进行,首先确定每个实体的候选关键字。一个 实体可能有若干候选关键字,选择其中对有关用户最熟悉的一个候选关键字作为主关键字(或主码),并将每个实体的候选关键字、主关键字记入数据字典。
确定实体间的联系
实际上,识别联系的主要任务是在需求分析阶段完成的。这里的工作一是从局部视图的角度进行一次审核,检查有无遗漏之处,二是确切地定义每一种联系。
在现实世界中,诸多形式的联系大致可分为三类:存在性联系
、功能性联系
和事件联系
。存在性联系如学校有教师、教师有学生、工厂有产品等;
功能性联系如教师讲授课程、教师参与科研等;事件联系如学生借书、产品发运等。
根据上述分类仔细检查在给定的局部视图范围内是否有未识别的联系,在确认所有的联系都已识别并无遗漏之后,还须对联系进行正确的定义。定义联系
就是对
联系语义的仔细分析,识别联系的类型,确定实体在联系中的参与度。
二元联系的类型与定义:
二元联系
是指两个实体类之间的联系。根据参与联系的两个实体类值之间的对应关系分为一对一、一对多及多对多 3 种类型。对每一种联系类型,要确定实体在
联系中的参与度,并以 m:n 的形式标在 E-R 图上要说明的实体旁,若 m>0 ,表明该实体参与联系是强制性的,若 m=0 则是非强制性的。下面分别讨论上述三类联系
的定义,以及另一种二元联系实体类内部的联系
。
- 一对一联系
这是一种最简单的联系类型。若对于实体集 A 中的每一个实体,实体集 B 中至多有一个实体与之联系,反之亦然,则称实体集 A 与实体集 B 具有一对一联系
,记为
1:1 。按照实体参与联系的强制性情况,又可分为以下 3 种情况:
(1)两类实体都是强制性的。加入规定每个工程师一定要负责一项工程,每项工程也一定要有一位工程师负责,便属于此种情况。如果工程师的辨识为职工号,工程标识 为工程号,对于工程师与工程间的 1:1 联系,可用职工号或工程号作为标识。
(2)其中仅有一类实体是强制性的。若规定每项工程必须由一名工程师负责,但并不是所有工程师都必须负责一项工程(因为可能没有那么多的工程),此时,每一项 工程一定对应着唯一的负责联系,所以工程号可用做联系的标识。
(3)两类实体均为非强制性的。如工程师不一定安排负责管理工程,有的工程项目暂时可以不安排工程师负责管理,这种情况标识凡分到工程项目的工程师与工程项目 之间总存在语义对应联系,因此职工号或工程号均可宣威负责联系的标识,定了其中一个为标识,另一个就作为候选关键字。
- 一对多联系:
若对于实体集 A 中的每一个实体,实体集 B 中有 n 个实体(n>=0)与之联系,反之,对于实体集 B 中的每一个实体,实体集 A 中之多有一个实体与之联系,则称
实体集 A 与实体集 B 有一对多的联系
,记为 1:n 。亿专业与学生间的关系为例:如规定一个专业可以管理许多学生,每个学生只能属于一个专业,这种联系就是一对多
联系。对这种联系我们只需关系“多”端实体的强制性,分两种情况进行讨论:
(1)“多”端的实体是强制性的。此时,每个学生必须归属某个专业,即每个学生都有一个确定的专业,但每个专业都不唯一地对应一个学生,故可以选择学号作为 联系的标识。
(2)“多”端的实体是非强制性的。对本例而言是指有些学生(如新生)不属于任何专业的情况。此时实际上仅标识已经分配专业的学生与专业之间的联系,对这些 学生中的每一个都有一个确定的专业,因此,应以学号为联系的标识,而专业代号作为联系的一般属性。
- 多对多联系
若对于实体集 A 中的每一个实体,实体集 B 中有 n 个实体(n>=0)与之联系,反过来,对实体集 B 中每一个实体,实体集 A 中也有 m 个实体(m>=0)与之联系,
则称实体集 A 与实体集 B 具有多对多联系
,记为 m:n。教师与学生这两个实体类间的教与学的联系就是多对多的联系。这是,只有<教师、学生>对才能确定
一个特定的教学联系。因此,一般情况下可以以两个关联实体的标识拼凑作为联系的标识。但这种方法对某些情况就不能构成有效的联系标识。当一个实体值在同一个
联系上可能存在多个不同的联系值时,就会出现这种情况。如教师与其讲授的课程之间的联系,同一个教师可讲授几门不同的课程,也可以多次讲授同一门课程,这是
一种特殊的多对多联系,这种情况可用下图所示的值图表示。
值图是表示具体实体及其关联的一种图示法,其中圆点表示具体的实体,连线表示实体间的联系。而通常的 E-R 图只能表示型而不是值,所以称为型图
。显然,
对于教师与讲授课程间的联系,如在教师档案中要求记录担任教学工作情况,就需要在联系标识中增加表示授课日期的属性,即其合适的联系标识可能为(教师号,
课程号,授课日期)。
- 实体类内部的联系:
这种联系发生在同一类实体的不同实体之间,因此称为内部联系
或自联系
,它也是一种二元联系,其表示方式与前面的二元联系并无不同,要注意仔细区别
同一实体类中的不同实体在联系中扮演的不同角色及联系标识的选择。例如在职工类实体中间就存在着管理者与被管理者的联系。
多元联系的识别与定义:
两个以上的实体类之间的联系称为多元联系
。例如在供应商向工程供应零件这类事件中,如果任一供应商可向任一工程供应任一种零件,则为了确定哪个供应商
向哪个工程供应了何种零件,就必须定义一个三元联系,因为只有供应商、工程及零件三者一起才能唯一地确定一个联系值。其联系的标识由参与联系的实体类的标识
拼接而成,在此例中由供应商、工程、零件 3 个实体类的标识拼接而成。
需要注意的是,涉及到多个实体的事件是否属于多元联系完全取决于问题的语义,不可一概而论。例如,如果上例中的问题说明变成每个工程需要订购一定的零件, 而任一供应商可向任一工程供应零件。这里有两层意思,一是只有工程确定了才能确定订购的零件,二是只有供应商及工程确定了,才能确定一个供应关系。根据这一 情况,应定义两个二元联系,如下图所示:
加入问题的说明是任意供应商向任一工程供应零件,但某个供应商向某项工程供应的零件是一定的,则在供应商与工程之间的关系确定后,供应的零件也就确定了。由此 可知,只需定义一个二元联系就可以了,如下图所示,其中供应商的零件作为供应联系的一个属性。
总之,具体问题应该具体分析,以便使定义的模式确切地表达问题的语义。
消除冗余联系:
若出现两个或两个以上的联系标识的是同一概念,则存在着冗余的联系,具有冗余联系的 E-R 模型转换为关系模型可能会得到非规范化的联系,因此必须予以消除。
出现冗余联系的一种重要原因是存在传递关系
。例如,下图中表示了产品与零件之间的“组成”联系,零件与材料之间的“消耗”联系及产品与材料间的“使用”
联系。其中,材料与零件间的联系是 1:n。零件与产品之间的组成联系是 n:m,其实由这两个联系必然得出产品与材料之间的使用关系 m:n。因此,图中产品与材料间
的联系是冗余的。应将其去掉。
警惕连接陷阱
连接陷阱
是一种存在语义缺陷的联系结构,它是由于在定义联系过程中对语义的理解出现偏差而造成的,因而无法由它得到需要的信息。连接陷阱可分为扇形陷阱、
断层陷阱和深层的扇形陷阱 3 种情况。
扇形陷阱:
两个实体类间的一对多联系。由一个实体值引出多个同一类型的联系值,其值图是一种扇形结构。下图(a)是这种结构的一个例子,图(b)是一个值图。从(b)值图 可以看出,从这种联系结构无法获得哪个职工属于哪个专科的信息,其原因是将专科与职工之间的联系通过医院来连接了。
如采用下图(a)所示的联系结构,图(b)是它的值图。新的结构能较自然地表示了医院、专科及职工之间的层次关联。假定任一医院的职工无例外地分属于医院的各个 专科的话,该结构可以确定一个职工所属的专科或医院,但如果允许某些职工直属医院而不属于任何专科,那么这种结构还是不合适的。
断层陷阱:
断层陷阱
是指型图所含的传递联系掩盖了某些特定的直接联系的现象。例如上图(a)的联系结构虽然隐含了医院与职工的联系(传递联系),但却没有提供部分
职工直属于医院的联系路径,因而出现了断层陷阱。解决办法是设置一个虚构的专科或增加一个联系,如在本例中增加一个医院-职工联系。增加虚构实体和现实世界不符,
因此可考虑增加一个联系,但增加新的联系在某些情况也可能带来新的麻烦,见下面的内容。
深层的扇形陷阱:
举一个“教师指导学生参加课题”的例子,若每个学生可在多位教师指导下参加多个课题研究,每位老师可知道多名学生,但现在只允许一名教师指导一名学生参加一个 课题,不允许多名教师指导同一名学生参加某个课题。对此可先建立一个由两个多对多的二元联系组成模式,如下图所示:
利用联系的分解法则将其分解为下图所示的结构,它是以学生为中心的双扇形结构。
下图是上图对应的值图,从该联系结构无法得到哪位教师指导哪个学生参加何课题的信息,这表明存在扇形缺陷。
下图是对上例的一种改进,在其中增加了一个教师与课题的联系。该联系结构能确切地提供“教师 1 指导学生 1 参与课题 1”及“教师 2 指导学生 2 参与课题 1”的 信息,但从此图无法确定教师 1 指导学生 2 参与了哪一个课题。对教师 2 和学生 1 也是如此,因为参加课题 1 或 2 均是正确的语义。之所以如此,原因在于新增加 的教师与课题间的多对多联系带来了两个新的双扇形结构,即=以教师为中心的及以课题为中心的双扇形结构。增加的新联系虽然消除了原来的陷阱,却产生了新的陷阱。
对这类问题的有效解决办法是将三个实体间的联系定义成一个单一的三元关系,它的 E-R 模型如下图所示。现在,每一个联系值唯一地确定了另一个联系值,从中可获得 哪位教师指导某学生参加哪一课题的确定信息。可见问题的实质是对于应该定义成三元关系的问题千万不能用二元联系代替。
分配实体及联系的属性
在需求分析中收集的数据对象集内,除去已识别的实体、联系及标识外,剩下的主要是非标识属性。问题的实质就是将这些非标识属性恰当地分配给有关实体或联系。 不过分配这些属性时,应避免使用用户不易理解的属性间的函数依赖关系有关准则,而应该从用户需求的概念上去识别框架中实体或联系必须有的描述属性,并按下述 两条原则分配属性。
非空值原则:
所谓非空值原则
是指当一个属性的分配在几个实体或联系中可以选择时,应避免使属性值出现空值的分配方案。例如在前面曾经讲过的工程师负责工程的模式中,
其联系是一对一且两个实体类均属非强制性的情况,现有一个属性项“施工期限”,按依赖关系考虑可加给工程师、工程或负责联系三者中的任何一个,因为工程师与
工程在这里是一对一的联系,工程师定了,工程的施工期限也就定了。但有的工程师可能没有分配到负责工程的任务,若把施工期限作为工程师的属性,在此情况下
便会出现空值;若作为工程的属性,则工程可能还未纳入计划,也会出现空值,可见将“施工期限”分配给负责联系最为适宜。
增加一个新的实体或联系:
在分配属性过程中,有时会出现有的数据项在框架模式中似乎找不到适合依附的实体或联系。对于这种情况,常常可通过在原模式中增加一个新的实体或联系加以解决。 例如,图 1-13 表示了一个病区/病人模式,这是一个一对多,且“多”端为强制性的联系,在所有明显的属性均已分配完后,尚有属性项手术名及手术号待分配。这里手术 名依赖于手术号,一个病人可能接受多种手术,一个病区可能接纳不同种手术的病人。在此情况下,手术号与手术名两个属性项不论作为哪个实体或联系的属性均不合适, 谓词可以在原来的模式中增加一个新的实体—手术,再加一个病人与手术的联系就可以了,如图 1-14 所示。
按照上述属性分配原则建立的模式将有利于转换成规范化的关系模式。
视图集成
视图集成
就是要将反映各用户组数据的局部数据模式综合成单位中某个确定范围内的单一数据视图,即全局数据模式
,又称模式汇总
。该全局数据模式
是未来数据库结构的基础,因此视图集成是数据库设计过程中一个十分重要的步骤,也是一项较为复杂和困难的任务。
当所有局部视图设计完毕后,就可开始视图集成了。整体 E-R 图包含了每个局部 E-R 图的信息,它合理地表示了一个简单而又完整的数据库概念模型。
视图集成的原理和策略:
视图集成的实质是所有局部视图的统一与合并,在此过程中主要使用了 3 个基本概念:等同、聚合和普遍化。基于这 3 个概念,有 3 种相应的基本集成方法。
- 等同:
等同
又称一致性合并,是指如果两个或多个数据对象具有相同的语义,则把它们归并为同一个对象,以消除不一致性,而不管它们的名字原来是否相同;同样,
如果两个对象有相同的名字,但表示不同的对象,则应通过改名把它们区分开来。
等同包括简单数据对象间的等同、多个数据对象的聚合与另外介个数据对象聚合之间的等同。等同的数据对象其语法表示形式不一定相同,它与通常所说的同义异名是 一个概念。识别等同时还要注意鉴别同名异义和语义相同但值域不同两种情况。同名异义虽有相同的表示形式,但语义却不同。等同貌似简单,但在实践中要做出判断 却并不容易,须做仔细分析,主要依靠对有关数据对象类值域的分析比较。
- 聚合:
聚合
表示和数据对象间的一种组成关系,例如数据对象学生可看成是学号、姓名、性别、年龄等数据元素的聚合。聚合集成
主要用于实体的属性分配,
有关的思想和方法请参看前面的实体分析法。
- 普遍化:
普遍化
是对某一概念范围内具有共性对象的一种抽象。在视图集成中,它用于对现实世界中的事物进行归类。虽然普遍化和聚合均表示事物的层次结构,且同一个数据
对象可能同时参与普遍化和聚合两种联系,但它们是两个截然不同的概念。聚合是将若干不同类型的数据对象组合成一个高级对象的过程,而普遍化是按公共属性的值
对事物进行抽象和归类的过程。
综合地运用上述三种方法可有效地进行视图的集成。视图集成从策略上可分成两类:二元集成
和 n(n>2)元集成:
- 二元集成:
- 平衡式;
- 阶梯式。
- n(n>2)元集成:
- 一次集成;
- 多次集成。
二元集成:
- 平衡式集成:
这种集成方式是把整个集成过程分成若干层次,在每层中进行亮亮集成,其结果进入下一层集成,集成的对数逐层减少,最后得到统一的视图。有人证明,只要选择 恰当的集成初始序列,就有可能使这种集成的分析比较次数达到最少。
两个分别具有 N 和 M 个对象的视图,其集成结果,在不考虑聚合和分解引起的增减的情况下,可能有 N+M-X 个对象,其中 X 为视图间对象的重叠度,若两个视图中 有 i 个对象等同,则 X = i-1.为了最大限度地减少在后面的集成中涉及的对象数,选择初始集成序列时应使没对集成视图的 X 值尽可能地大,若在每个集成层次上 均彼此原则进行,则就可能使总的集成效率达到最高。只有当配对的是关系极为密切的视图,即对应于事务处理中联系最紧密的功能域时,才能使配对视图中的 X 值为 最大。由此可见,确定视图初始集成序列中的分组原则与划定局部范围的原则是一致的,因而有关的方法也是可参照使用的。
- 阶梯式集成:
阶梯式集成是一种流水线作业形式的集成方式,它无须考虑视图的初始序列,当然也不保证 X 值为最大,但省去了进行处理的麻烦,且这种方案适合同已经存在的局部集成模式 进行综合。数据库的应用范围常常随着单位的发展而需要逐步扩展,扩展的每一种功能所设计的数据,通常与已经集成的数据模式关联最为密切,而阶梯式集成为 这种情况提供了最为适宜的策略。
由以上可知,二元集成是一种较简单且行之有效的策略。它的优点在于可使每个集成步骤上的分析比较过程简单化和一致化,因而使用较广泛。它的主要缺点是集成操作 的总次数较多,且在最后必须分析检查是否满足总体性能,必要时须做调整。
n 元集成:
- 一次集成:
此法一次集成 n 个视图。其优点是能充分地考虑全局需求,不必到最后再来分析调整,且集成操作次数少。缺点是集成效率将随着视图数及视图中对象数的增加而明显 降低,因为集成过程中基本操作是等同性检查,一次集成 n 个视图,为了判别一个视图中单个数据对象的等同性,必须与其他 n-1 个视图中的每个数据对象进行比较, 所以只有当 n 较小时,这种策略才有意义。
- 多次集成:
此法先用与平衡式二元集成相同的机理,将待集成的视图分成若干组,每组的视图数可以是两个或多个,但个数不能太多,然后按组集成,形成若干中间视图,再对 这些中间视图进行分组、集成,最后得到全局视图。它的优点是:具有平衡式二元集成法效率较高的优点,集成操作的总次数较少;齐次,其分层的集成过程在概念 上正好与大多数具有层次功能结构的事务单位相吻合。事务管理人员可凭借其丰富的事务知识有效地进行低层次集成,单位中高级管理人员具有的综合知识及全局观点, 有利于运用聚合或普遍化感念进行高层次上的集成。此策略的效果同样取决于初始集成序列的划分。它的缺点是一致性差。
视图集成的方法和步骤
局部视图集成是一个相当困难的工作,往往必须凭设计者的经验与技巧才能很好地完成。尽管如此,集成的方法很多,它因所用的概念设计数据模型、集成策略、集成
过程的输入/输出量及识别和解决冲突的方法的不同而各有其独特的执行过程,但总的来说都分成两个阶段:预集成阶段
和集成极端
。
预集成阶段:
- 确定总的集成策略,包括视图集成的优先次序,一次集成的视图数及初始集成序列等;
- 检查集成过程要用到的信息是否齐全;
-
揭示和解决冲突,为下阶段的视图归并奠定基础。
集成阶段:
集成阶段
的主要任务是归并和重构局部视图,最后得到统一的全局视图。全局视图须满足下述要求:
- 完整性和正确性:整体视图应包含各局部视图所表达的所有语义,正确地表达与所有局部视图应用相关的数据观点;
- 最小化:原则上,现实世界统一概念只在一个地方表示。
- 可理解性:即应选择最易为设计者和用户理解的模式结构。
一个视图的基本框架主要由实体和联系组成,所以集成主要是实体与联系的集成,整个集成过程也就是这两类基本集成过程的反复交替执行的过程。
等同的识别和冲突的发现与解决
冲突的表示及处理策略
- 同名异义:
为了发现不同视图间的同名异义问题,可以先列出所有同名数据对象,然后诸一判别其语义。对同名异义冲突通常采用换名加以解决,既可对同名者之一换名,也可对 两者都给以重新命名。识别语义的主要方法是进行值域分析。
- 异名同义:
识别异名同义比较困难,一般由设计者对所有对象一个不漏地逐一鉴别(最好开始设计局部视图时约定命名规则和常用名称)。它同样采用换名的方法解决。若归并时 视图将它们合并为一个对象,则可以把其中之一的名称作为合并后的对象名;若集成后,它们仍以两个不同的对象存在,则可对其一换名,当然,若原名都不合适,则 可以对两者都重新命名。
- 同名不同层次:
如果两个对象同名,但其中之一是作为一个视图中的实体,而另一个是另一视图中的属性,则在集成时就会发生同名不同层次的冲突。解决这种冲突的办法的两个,一是 将属性转换为实体,而是将实体变换成属性。例如,设一局部视图中有一部分实体 DEPT,而在另一与之集成的视图中有职工实体 EMP,且 EMP 有属性 DEPT,于是发生了 同名不同层次的冲突。此时,可将 EMP 的 DEPT 属性去掉,另设一个实体 DEPT 与 EMP 建立联系,这时再与另一视图集成就容易多了。再如,设一局部视图中有一名 为 STOR 的仓库实体,其中含有一属性部门号(DEPT-NO);在另一局部视图中有一单位实体 DEPT,其中仅含有一个属性 DEPT-NO。对这类同名不同层次的冲突, 可将 DEPT 实体变换为其所在视图中与 DEPT 相关的另一实体的属性,然后再进行集成。必须注意的是,实体变换为属性时通常要满足一些特定的条件,比如该实体 通常只有一个与同名属性具有共同特征的属性,且一定存在一个与该实体存在联系的另外的实体。
- 同名同义联系测度冲突:
虽同名同义,但对象联系刻度不同。所谓联系测度
是指实体的联系是一对一、一对多还是多对多。若同名同义对象的在一个局部视图中为一对多联系,在另一局部
视图中为多对多联系,则在集成时将发生联系测度冲突。一般而言,一对多包含一朵一,多对多包含一对多。所以解决这种冲突的方法往往取较高刻度为集成后的相应
的测度。
- 约束冲突:
不同视图可能有不同的约束,例如,对于“选课”这个联系,大学生和研究生对选课的最少门数和最多门熟可能不一样。
- 数据特征不相容:
如果一同名同义属性在一局部视图中刻作为关键字属性,但在另一局部视图中不具有关键字属性特征;或者,如果一组属性在不同视图中具有相反的相互依赖关系。这 联众情况均会发生数据特征不相容冲突。对于第一种不相容冲突,集成时往往需要重新选择关键字;关于第二种不相容冲突,解决的策略则依赖于实际应用环境。例如, 假设在两个不同局部视图中都含有课程和教室属性,其中之一存在课程决定教室的属性依赖关系,而在另一局部视图中课程与教室的依赖关系刚好相反。当将这两个 属性集成到一个实体中时,其原有的这种对应联系将不存在。此时,若这种联系的丢失不产生影响,则集成可正常进行。但如同第一种冲突,有时可能要重新指定关键字, 而且,有时第二种冲突也可鞥具有第一种冲突的特征,本例就可能是这种情况。
不相容冲突因不同的环境而可能有多种不同的形式,应根据具体情况采用不同策略加以灵活处理。
等价数据对象类之间的映射:
另一类貌似不等同但通过适当映射可转化为等同的数据对象,称为等价的数据对象类。通常有两种等价情况:
(1)用不同的名称和值域描述统一种食物。例如,出生日期(日期型)与年龄(整型)、职工号(字符型)与工作证号(整型)等。
(2)用不同的度量单位度量同一事物。对于“重量”“长度”等度量属性都可能出现这一情况。如对于一个物品的重量单位在一个视图中定义为吨,而在另外的视图中 定义为公斤。这两种情况实质是用不同的形式来描述统一事务或概念,这种描述统一事物或概念的数据对象类称为等价数据对象类。这些等价数据对象之间可以按一定 的规则映射,如出生日期与年龄之间,吨与公斤之间都可按公式进行相互转换,对那些没有确定的规则可循的等价数据对象类之间的映射可用对照表加以实现。
等价数据对象类
是由于各个用户组对数据对象的观点不同而造成的。它们可以通过映射转化为等同数据类,然后再按等同数据对象进行集成。因此,在集成前应
仔细识别所有等价数据对象类,并确切说明它们之间的映射。
定义数据对象类的值域:
一个数据对象类所有可能的实例的集合称为该对象类的值域
或简称为域
。数据对象类的值域是分析该数据对象类语义的重要依据,是识别各个视图中数据
对象类在所讨论的概念上是等同的、有共性或不相干的主要依据。因此仔细定义每个数据对象的值域是识别来自不同视图的数据对象类是否等同的主要手段。例如 Dom(A) 表示
对象类 A 的值域,各对象类在值域上存在四种相关情况。
- 域等同;
- 域包含(子集关系);
- 域重叠(有交集);
- 域分离(无交集)。
对所有数据对象按上述四种值域相关情况归类后,便可用不同的方法对实体类进行集成。
实体类的集成
下面按照前面定义的四种值域相关情况,采用二元集成策略,对视图中的实体类进行集成。为了方便起见,用大写字母,如 A、B 等表示实体类,用 Attrs(A) 表示 实体类 A 的属性。
- 域等同:
A 和 B 是来自不同视图的两个实体,如果它们的值域等同,则集成过程就是建立一个单一的实体类,设为 C,作为全局模式中的实体类,其属性 Attrs(C) 为 A 和 B 的 属性的并集,值域等同于 A 或 B 的值。因此,在这种情况下,集成操作就变成了求并操作,可表示为:
- 域包含:
- 域重叠:
- 域分离:
联系类的集成
联系类集成
是通过语义分析来归并和调整来自不同视图的联系结构。联系的语义主要由里阿尼的元数、实体在联系中角色和参与度,以及联系的值域等表示。
根据待集成联系类的元数和实体在联系中所起角色的异同,可将联系类的集成分成三种类型:
- 元素和角色均相同的联系类的集成;
- 不同角色的联系类的集成;
- 不同元数的联系类的集成。
其中每一种类型又可按实体的参与度或值域等语义因素分为八种情况。下面对它们逐一进行讨论。
元素和角色均相同的联系类的集成
- 实体的参与度相同:
- 实体的参与度不同:
不同角色的联系类的集成
- 域包含:
- 域分离:
在这种情况下,参与两个不同视图中联系类的实体虽然相同,但它们表示的却是通常意义上互不相干的两件事。集成时,它们会变成全局模式中两个实体类间的两个联系。
- 域重叠:
不同元数的联系类的集成
不同元数的两个联系类之间有三种可能的情况:
(1)元数较少的联系类可从元数较多的哪个联系类导出。
(2)两个联系类在施加某些语义限制后可以兼容。
(3)不属于以上两种情况。
对应地有三类集成处理:可归并的、有条件可归并的和不可归并的。
- 可归并的不同元数的联系类:
- 有条件可归并的联系类:
- 不可归并的联系类:
新老数据模式的集成
当需要对已经建立的数据库系统进行扩充、修改、以扩大其应用范围,满足企业业务上发展的需要时,就会出现新老数据模式的集成问题。
现有的数据库系统的情况可能是:
- 由若干面向单项应用的独立数据库组成;
- 支持一定范围内多项应用的综合数据库。
不论哪一种情况,均可应用前面所讲的方法进行集成处理,但其具体内容稍有不同。
原有系统为多个独立数据库时的集成
这种情况下的集成包括单个数据库的集成和扩充的数据模式的集成。由于这些独立的数据库仅仅各自反映单个用户组的需求,而且很可能是在不同时期由不同的设计人员 设计的,因而这些数据库之间及其和扩充的数据模式之间。必然地存在许多冲突和冗余。把它们集成为一个能支持所有应用,并能保证数据的一致性、完整性及最小 冗余的全局模式后,原有的应用程序很可能都不能运行。因此,事前需要有周密的计划,原则是既要满足新的需要,同时尽可能地保持原来的数据模式,以便将原有的 应用程序稍做改动后仍能运行。
原有系统为单一的综合数据库时的集成
这时原有的数据模式已是经过集成的数据模式,再和扩充部分集成时,应尽量地向原模式靠拢,以使得原数据库支持的应用程序基本不变。
进行新老数据模式集成时,首先必须理解原有数据模式。如果原有数据库未留下概念设计的文档,那么就得从分析模式入手,这一过程不但十分困难和繁琐,而且容易 出错或遗漏。因此,对于比较复杂的数据模式,最好先将逻辑模式翻译成相应的 E-R 图,将其与用户交互,确认新的需求,根据用户意见,对 E-R 模式进行调整,形成 新的用户视图,然后再按前面所述的方法集成。可见,新老数据模式的集成比全新的视图集成受到的限制更多,因此,在某种意义上来说更加困难。
事务的设计
数据库设计的目的是支持各种事务的运行,在数据库设计的过程中,需要考虑所有事务的特点和要求。这样才能保证所设计的数据库包含各种事务所需要的信息。事务 的各种特点和性能要求在物理数据库设计中也是非常重要的。当然,在概念数据库设计阶段,我们不可能知道所有的事务。但是,数据库系统的重要事务常常是可以 预先知道的。数据库设计应该以这些事务为依据。所以,事务的设计通常是与数据库设计同时进行的。在概念数据库设计阶段,事务设计的任务是定义事务的功能。 在概念级定义事务功能的方法是说明事务的输入信息、输出信息和功能。使用这种方法,事务的定义可以独立于任何数据库管理系统。
事务可以分为三类:
- 数据查询型事务:
这类事务查询数据库中的数据,进行各种数据处理。
- 数据更新型事务:
这类事务用于增加、修改和删除数据库中的数据。
- 混合型事务:
这类事务既具有查询功能也具有更新功能。
逻辑结构(数据库)设计
概念结构
````独立于任何一种数据模型的信息结构。逻辑结构设计
的任务就是把概念结构设计阶段设计好的基本 E-R 图转换为与选用的 DBMS 产品所支持的
数据模型相符合的逻辑结构。可见逻辑数据库设计依赖于逻辑数据模型(有关系模型、层状模型和网状模型)和数据库管理系统。
从理论上讲,设计逻辑结构应该选择最适于相应概念结构的数据模型,然后对支持这种数据模型的各种 DBMS 进行比较,从中选出最合适的 DBMS。但实际情况往往是已给定 了某种 DBMS,设计人员没有选择的余地。
逻辑数据库设计的目标:
- 满足用户的完整性和安全性要求;
- 动态关系至少具有第三规范形式,静态关系至少具有第一范式;
- 能够在逻辑级上高效率地支持各种数据库事务的运行;
- 存储空间利用率高。
目前 DBMS 产品一般支持关系、网状、层次三种模型中的某一种。对莫一种数据模型,各个机器系统又有许多不同的限制,提供不同的环境与工具。所以设计逻辑结构时 一般要分 3 步进行:
- 将概念结构转换为一般的关系、网状、层次模型;
- 将装换来的关系、网状、层次模型向特定 DBMS 支持下的数据模型转换;
- 对数据模型进行优化。
对于关系数据库的逻辑设计阶段的步骤如下:
- 形成初始关系数据库模式;
- 关系模式规范化;
- 关系模式优化;
- 定义关系上的完整性和安全性约束;
- 子模式定义;
- 性能估计。
形成初始关系数据库模式
初始关系数据库模式
是指直接由概念数据库模式生成的关系数据库模式。初始关系数据库模式生成的目的
是把概念数据库模式的实体、实体间联系等模型结构
变换为关系模式。
普通实体型的转换
弱实体的变换
多值属性的变换
带有非原子属性的实体的转换
实体间联系的变换
- 1:1 联系的变换:
- 1:N 联系的变换:
- M:N 联系的变换:
- n 元联系的变换:
超类/子类联系的变换
扩充 E-R 模型向关系模型的转换
扩充 E-R 模型是基本 E-R 模型的扩充。它主要扩充了两点:
- 一是一个实体集可能是另一个实体集中的某个属性,即一个实体可以附属于另一个实体集;
- 二是增加了一种叫 is-a 的特殊联系,这种联系建立了两个实体间的继承关系,通过这种联系可以构成实体集之间的普通化/特殊化层次结构。
下面讨论这些扩充部分的转换,这些转换方法也可推广到其他具有这些概念的数据模型。
- 1)一个实体集同时是另一个实体集的属性:
- 2)两个实体集间 ISA 联系的转换
- 3)一个超集具有多个子集时的转换
范畴和共享子类的变换
一般关系模型向特定的关系模型的转换
确定函数依赖集
通过前面的变化,概念数据库模式中的所有模型结构都已经变换为关系模式,形成了初始关系数据库模式。最后,我们需要对初始关系数据库模式中的每个关系模式进行 深入地分析,与用户协商,确定每个初始关系的函数依赖集,使用关系数据库设计理论,对关系模式进行规范化处理。
逻辑模式的规范化和优化
从 E/R 图转换而来的关系模式还只是逻辑模式的雏形,要称为逻辑模式,还需要进行下列及步的处理:
- 规范化;
- 适应 DBMS 限制条件的要求;
- 对性能,存储空间等的优化;
- 用 DBMS 锁提供的 DDL 定义逻辑模式。
下面主要讨论对性能、存储空间等的优化。
(1)数据库性能的优化:
- 减少连接运算:
- 减小关系的大小和数据量:
- 尽可能使用快照:
(2)节省存储空间的措施
- 节省每个属性所占的空间:
- 采用假属性减少重复数据所占存储空间:
另外,数据库逻辑设计的结果不是唯一的。为了进一步提高数据库应用系统的性能,还应该根据应用需要是当地修改、调整数据模型的结构,这就是数据模型的优化
、
关系数据模型的优化通常以规范化
理论为指导,方法(至于涉及到的理论和细节请参考前面相关内容的表述)为:
- 确定数据依赖:
根据数据依赖的概念分析和表示数据项之间的联系相关内容,写出每个数据项之间的数据依赖。按需求分析阶段所得到的语义,分别写出每个关系模式内部各属性之间的 数据依赖以及不同关系模式属性之间的数据依赖。
- 数据依赖极小化处理:
对于各个关系模式之间的数据依赖进行极小化处理,消除冗余的联系。
- 范式分析:
按照数据依赖的理论对关系模式逐一进行分析,考察是否存在部分函数依赖、传递函数依赖、多值依赖等,确定个关系模式分别属于第几范式。
- 模式合并或分解:
按照需求分析阶段得到的处理要求,分析对于这样的应用环境,这些模式是否合适,确定是否要对默写模式进行合并或分解。
- 模式分解:
对关系模式进行必要的分解,提高数据操作的效率和存储空间的利用率。常用的两种分解方法是水平分解和处置分解。
规范化评论为数据库设计人员判断关系模式优劣提供了理论标准,可用来预测模式可能出现的问题,使数据库设计工作有了严格的理论依据。
设计用户子模式
将概念模式转换为全局逻辑模型后,还应该根据局部应用需求,结合具体 DBMS 的特点,设计用户的外模式。
目前关系数据库管理系统一般都提供了视图概念,可以利用这一功能设计更符合局部用户需要的用户外模式。
定义数据库全局模式
主要是从系统的时间效率、空间效率、易维护等角度出发。由于用户外模式与模式是相对独立的,因此在定义用户外模式时可以注意考虑用户
习惯于方便。包括:
- 使用更符合用户习惯的别名:
- 可以对不同级别的用户定义不同的视图,以保证系统的安全性。
- 简化用户对系统的使用:
如果某些局部应用中经常要使用某些很复杂的查询,为了方便用户,可以将这些复杂查询定义为视图,用户每次只对定义好的视图进行查询,大大简化了用户的使用。
评审设计
评审设计的主要内容是对概念模式的质量和性能进行评价,以便改进。
- 模式的评价:
- 数据模式的改进:
数据库的物理设计
数据库在物理设备上的存储结构与存取方法称为数据库的物理结构
,它依赖于选定的数据库管理系统。为一个给定的逻辑数据模型选取一个最适合应用要求的物理结构
的过程,就是数据库的物理设计
。
物理数据库设计的任务
是在数据库逻辑设计的基础上,为每个关系模式选择合适的存储结构和存取路径。和逻辑模式不一样,它不直接面向用户。一般的用户不一定
也不需要了解数据库存储模式的细节。所以数据库存储模式的设计可以不必考虑用户理解是否方便。数据库物理设计的目标有两个:
- 提高数据库的性能;
- 有效地利用存储空间。
在这两个目标中,第一个目标更为重要,因为性能仍然是当今数据库系统的薄弱环节。
总之,数据库物理设计是利用已确定的逻辑结构及 DBMS 提供的方法、技术、以较优的存储结构、数据存取路径、合理的数据存储位置及存储分配,设计出一个高效的、可实现 的物理数据库结构。显然,数据库的物理设计是完全依赖于给定的硬件环境和数据库产品的。
数据库的物理设计分为如下 4 个步骤:
- 分析影响数据库物理设计的因素;
- 为关系模式选择存取方法;
- 设计关系、索引等数据库文件的物理存储结构;
- 对物理结构进行评价,评价的重点是时间和空间效率。
每个数据库管理系统都提供很多种存储结构和存取方法供数据库设计者选择。物理数据库设计与数据库管理系统密切相关。如果评价结果满足原设计要求,则可进入到物理 实施阶段,否则,就需要重新设计或修改物理结构,有时甚至要返回逻辑设计阶段修改数据模型。
由于不同的 DBMS 提供的硬件环境和存储结构、存取方法、以及提供给数据库设计者的系统参数、变化范围有所不同,因此,为了设计出一个较好的存储模式,设计者必须 了解一下几方面的问题,做到心中有数。
(1)了解并熟悉应用要求,包括各个用户对应的数据视图,即数据库的外模式(子模式),分清哪些是主要的应用,了解各个应用的使用方式,数据量和处理频率等,以便 对时间和空间进行平衡,并保证优先满足应用的时间要求。
(2)熟悉使用的 DBMS 的性能,包括 DBMS 的功能,提供的物理环境、存储结构、存取方法和可利用的工具。
(3)了解存放数据的外存设备的特性,如物理存储区域的划分原则,物理块的大小等有关规定及 I/O 特性等。
设计方法与内容
在进行物理设计时,设计人员可能用到的数据库产品是多种多样的。不同的数据库产品所提供的物理环境、存储结构和存取方法有很大差别,能供设计人员使用的设计变量、 参数范围也大不相同,因此没有通用的物理设计方法可遵循,只能给出一般的设计内容和原则。
数据库物理设计包括数据存储结构的设计、集簇的设计、存取路径的设计和确定系统配置几个方面。
- 数据存储结构的设计:
- 集簇的设计:
- 存取路径的设计:
- 确定系统配置:
影响物理设计的因素
给定一个数据库逻辑模式和一个数据库管理系统,有大量的数据库物理设计策略可供选择。我们希望选择优化的数据库物理设计策略,使得各种事务的响应时间最小、事务 吞吐率最大。要做出这样的选择,我们必须在选择存储结构和存取方法之前,对数据库系统支持的事务进行详细分析,获得选择优化数据库物理设计策略所需要的参数。
对于数据库查询事务,我们需要得到如下信息:
- 要查询的关系;
- 查询条件(即选择条件)所涉及的属性;
- 连接条件所涉及的属性;
- 查询的投影属性。
对于数据更新事务,我们需要得到如下信息:
- 要更新的关系;
- 每个关系上的更新操作的类型;
- 删除和修改操作条件所涉及的属性;
- 修改操作要更改的属性值。
上述这些信息是我们确定关系的存取方法的依据。除此之外,我们还需要知道每个事务在各关系上运行的频率,某些事务可能具有严格的性能要求。例如,某个事务必须在 20 秒内结束。这种时间约束对于存取方法的选择具有重大的影响。我们需要了解每个事务的时间约束。
如果一个关系的更新频率很高,这个关系上定义的索引等存取方法的数量应该尽量减少。这是因为更新一个关系时,我们必须对这个关系上的所有存取方法作相应的修改。
值得注意的是,在进行数据库物理设计时,我们通常并不知道所有的事务。上述信息可能不完全。所以,以后可能需要修改根据上述信息设计的物理结构,以适应新事务的 要求。
存取方法的选择
数据库系统是多用户共享的系统,对同一个关系要建立多条存取路径才能满足多用户的多种应用要求。物理设计的任务之一就是要确定选择哪些存取方法,即建立哪些 存取路径。
存取方法设计的目标是:提供访问每个记录类型或关系的存取方法,使得主要应用能对它们做最有效的访问,它包括文件结构和索引选择两个方面。
数据库访问类型
虽然对数据库的访问要求是多种多样的,但就文件结构的选择而言,大致可分为三种类型:
- 访问文件的全部或相当多的记录:属于这类访问的应用一般要访问 20%~100% 的记录。
- 访问某一特定记录:
- 访问某些记录、
文件类型的选择
有些 DBMS 是以操作系统的文件管理系统为其物理层的基础。但更多的 DBMS 是独立设计其物理层,其原因是:
(1)DBMS 为了实现其功能,需要在文件目录、文件描述块、物理块等部分增加一些信息,传统的文件系统无此功能。
(2)数据库中的文件为所有用户共享,要求其结构能兼顾多方面的要求,提供多种访问途径,提供并发控制、故障恢复和保密等方面的手段,而传统文件则无法满足这些要求。
(3)传统文件系统主要面向批处理,在数据库系统中,往往要求及时访问、动态修改、要求文件结构能够适应数据的动态变化,提供快速访问路径。
(4)若以操作系统中的文件系统为 DBMS 物理层的基础,则因 DBMS 对操作系统的依赖性,不利于 DBMS 的移植。何况,有些操作系统,如 UNIX,仅提供字符流的存取功能 ,不提供各种文件结构,只能靠 DBMS 本身来实现。
(5)数据文件的数据量变化大,传统文件无法适应这样的变化。
因此,DBMS 的文件结构虽然继承了文件系统的某些技术,但又与传统文件系统有区别。数据库物理设计不是设计和实现新的文件结构,而是在 DBMS 所提供的各种文件结构 范围内,根据应用的要求和数据的特征,选择适当的文件结构。
各个 DBMS 提供的文件结构和访问方法虽然有所不同,但常用的一般有以下几种:
- 直接文件(HASH):
在这种文件中,通过记录的关键字映射成记录的地址,直接访问该记录,与记录在文件中的文职及文件的大小无关,因此是随机的。郑重文件不但查找方便,插入、删除、修改 也很方便。关于关键字到地址的转换用各种散列函数实现。直接文件虽然能快速随机地查找文件中的某些记录,但由于某些原因,在目前数据库系统中很少作为通用的访问 方法,仅用于需要快速随机查询的场合,如数据字典的查询。
影响直接文件在数据库系统中使用的原因主要有:
(1)关键字所映射的地址空间并不取决于实际的数据量,而取决于关键字所映射的地址范围,因而往往造成存储空间的极大浪费。
(2)不同的关键字可能映射到同一地址,对应每个映射地址有一个桶。当桶装满了,就会溢出,这时就要进行溢出处理,增加了访问的开销,若出现严重的溢出情况,就会 使想能恶化。
(3)只能通过关键字直接访问,访问方法比较单一,适用于上述第二种类型的某些访问,对于其他类型的访问就非常不便。
(4)不便于处理变长记录。
(5)对于通用的 DBMS 很难找到合适的、通用的散列函数。
- 堆文件:
在这种文件结构中,记录按其插入的先后次序存放。记录可以存放在一个邻接的存储区中,也可以存放在多个不相邻接的存储区中,甚至可以存放在一个个物理上不相邻接的
物理块中国,通过指针或逻辑地址到物理地址的映射表等机制连成一体。这种文件结构的优点
是:建立容易,插入也很方便。缺点
是:一般之鞥女采用顺序的
扫描方式进行搜索。适宜于第一种类型的访问,对于其余两种类型的访问,效率很低,其次,删除、修改困难,一般在删除时只做删除标志,并不立即进行物理上的删除,
以避免引起大量记录的移动,而是在积累了一定数量的删除记录后,再集中清理,一般小文件都用堆文件,因为对于小文件不值得提供其他复杂的访问机制,尤其当内存缓冲区
较大时,有些小文件可直接调入内存处理,速度很快。对于大文件,堆文件主要用于第一种类型的访问。
- 索引文件:
实际上,索引文件
是在前述的堆文件上增加了索引。索引
相当于一个映射机构,把某一键值转换为记录的地址。它与散列法的区别
在于:索引法在有了记录
后,才有索引项,才占有存储空间,因而不会浪费存储空间。当然,索引本身也要占用一定的空间,但索引键比记录本身要小得多,为此付出的代价是可以接受的。此外,
索引键的选择也比较灵活,可以是单属性,也可以是多个属性的组合,而且还可根据需要建立多种或多级索引。索引文件按其是否根据索引键排序而分为顺序文件
和
非顺序文件
。
在堆文件的基础上加上索引后,既可利用原来的堆文件处理大量的记录,又可以利用索引访问个别记录,较好地满足了前述三种类型访问的需要,因而在数据库系统中得到了 广泛应用,尤其是 B 树动态索引用得最多。
索引的选择
原则上讲,索引选择可以采用穷举法,对每种可能的方案进行代价估算,从中选择最佳的方案,但实际上这是行不通的,其原因如下:
(1)数据库中文件之间的相关性。例如,关系数据库中的连接操作涉及多个文件,在计算连接操作的代价时,往往在其他关系参与连接操作的方法有关,因而各个文件往往 不能孤立地进行设计。
(2)可能出现组合爆炸问题
,难以进行计算。即使对于由五个文件组成的数据库,每个文件只有五个属性的话,如果在单个属性上建立索引,其存取结构的可能方案
就有10的11次方之多。实际的数据库文件一般远远不止五个,每个文件的属性也不止五个,而且有可能需要在多个属性上建立索引,这样的求解空间显然太大了。
(3)访问路径与 DBMS 的优化策略有关。一个事务究竟如何之赐你个,不仅取决于数据库设计者提供的访问路径,还取决于 DBMS 的优化策略。若设计者所认为的事务执行 方式与 DBMS 实际执行事务的方式不同,就会出现设计结果与实际情况的偏差。
(4)代价估算比较困难。首先因为代价模型与系统有关,很难形成一套通用的代价估算公式;其次,代价估算与数据库本身特性有关,为了获得必须的设计参数,必须对 数据库进行统计分析,而在数据库设计阶段,对数据特性的了解往往是不充分的。
(5)设计目标较为复杂。鉴于上述原因,很难进行比价精确、优化的数据库物理设计,目前常用的是一种简化了的设计方法,其思想和基本方法如下所述。
有人分析了各种连接方法后认为,在一定条件的限制下,某些连接方法是可分离的,换句话说参与连接的各个关系的代价可以独立地估算,对于像嵌套循环法进行两个关系连接
等不可分离的连接方法,即使按分离的方法处理,也不会引起显著的误差。因此,在进行数据库物理设计时,可以分别设计各个文件,从而避免了前面提到的组合爆炸问题,
大大缩减了求解空间。该理论课称为可分离理论
。
按照可分离理论,根据处理要求,对记录在文件中的存放方式—有序或无序或按某一属性(或属性组)进行集簇等,做出初步的抉择,将在运行中进行适当调整,而不必 穷军各种可能,从而把问题归结为一个文件要建立哪些索引。而且经过简单分析后,可确定在有些属性上不需要建立索引,当然也不需要进行代价分析和比较了,不需要建立 索引的属性有:
- 在查找条件中不出现或很少出现的属性;
- 属性值很少的属性:
因为对于这种情况,如果在其上建立属性,则在每个索引项后面会附有大量的 tid(元组标识符—此块号和记录在块中的地址组成),顺序索引集的溢出块将会很多, 用索引去检索,不如直接进行顺序扫描。
建立索引的一般原则为:
(1)如果某个(或某些)属性经常作为查询条件,则考虑在这个(或这些)属性上建立索引。
(2)如果某个(或某些)属性经常作为表的连接条件,则考虑在这个(或这些)属性上建立索引。
(3)如果某个属性经常作为分组的依据列,则考虑在这个(或这些)属性上建立索引。
(4)为经常进行连接操作的表建立索引。一个表可以建立多个索引,但只能建立一个聚簇索引。
注意事项:
索引一般可以提高查询性能,但会降低数据的修改性能。因为在修改数据时,系统要同时对索引进行维护,使索引与数据保持一致。维护索引要占用相当多的时间,而且存放 索引信息也会占用空间资源。因此在决定是否建立索引时,要权衡数据库的操作,如果查询多,并且对查询的性能要求比较高,则可以考虑多建一些索引。如果数据更改较多, 并且对更改的效率要求比较高,则应该考虑少建一些索引。
总结:
在手工设计时,一般按启发式规则
选择索引。即使在数据库的计算机辅助设计工具中,也是先用启发式规则限制选择范围,在用简化的代价比较法选择索引。下面
介绍用启发式规则选择索引的一般步骤:
(1)凡是满足下列条件之一的属性或表,不宜建立索引:
- 不出现或很少出现在查询条件中的属性。
- 属性值很少的属性。例如属性“性别”只有两个值,若在其上建立索引,则平均起来,每个属性值对应一半的元组,用索引检索,还不如顺序扫描。
- 属性值分布严重不均的属性或表。因为更新时有关的索引需要做相应的修改。
- 过长的属性。例如超过 30 个字节。因为在过长的属性上建立索引,索引所占的存储空间较大,而索引级数也随之增加,有诸多不利之处。如果实在需要在其上建立索引, 必须采取索引树荫属性压缩措施。
- 太小的表。例如小于留个物理块的表。因为采用顺序扫描最多也不过六次 I/O,不值得采用索引。
(2)凡符合下列条件之一,可以考虑在有关属性上建立索引,下面所指的查询都是常用的或重要的查询。
- 主键码和外键码上一般都建有索引,这有利于主键码位移性检查和引用完整性约束检查;主键码和外键码通常都是连接条件中的公共属性,建立索引,可显著提高连接查询 的效率。
- 对于以读为主或只读的表,只要需要,存储空间又允许,可以多建索引。
- 对于等值查询(即查询条件以等号为比较符),如果满足条件的元组是少量的,例如小于 5%,且存储空间允许,可以考虑在有关属性上建立索引。
- 对于范围查询(即查询条件以
<、>
等为比较符),可以在有关的属性上建立索引。 - 有些可以从索引直接得到结果,不必访问数据块。对于这种查询,在有关属性上建立索引是有利的。
上述选择索引的规则仅仅是原则性的。也许有些索引既有建立的理由,又有不宜建立的理由,这只能由设计者权衡。好在数据库在运行以后,还可以调整。有些索引一时难以 决定是否建立,可以等到运行时通过实验来确定。
聚簇存取方法的选择
为了提高某个属性(或属性组)的查询速度,把这个或这些属性(称为聚簇码
)上具有相同值的元组集中存放在连续的物理块称为聚簇
。聚簇方法是把经常进行
连接操作的多个关系的记录以连接属性为中心分类存储。聚簇方法可以提高连接操作的效率。
聚簇功能不但适用于单个关系,也适用于经常进行连接操作的多个关系。即把多个连接关系的元组按连接属性值聚集存放,聚簇中的连接属性称为聚簇码
。这就相当于
把多个关系按“预连接”的形式存放,从而大大提高连接操作的效率。
一个数据库可建立多个聚簇,一个关系只能加入一个聚簇。
选择聚簇存取方法,即确定需要建立多少个聚簇,每个聚簇包含哪些关系。下面先设计候选聚簇,一般来说:
- 对经常在一起进行连接操作的关系可以建立聚簇;
- 如果一个关系的一组属性经常出现在相等比较条件中,则该单个关系问题可建立聚簇;
- 如果一个关系的一个(或一组)属性上的值重复率很高,则此单个关系可建立集簇。即对应每个集簇码值的平均元组数不太少。太少了,集簇的效果不明显。
然后检查候选聚簇中的关系,取消其中不必要的关系:
- 从聚簇中删除经常进行全表扫描的关系;
- 从聚簇中删除更新操作远多于连接操作的关系;
- 不同的聚簇中可能包含相同的关系。一个关系可以在某一个聚簇中,但不能同时加入多个聚簇。要从这多个聚簇方案(包括不建立聚簇)中选择一个较优的,即在这个聚簇 上运行各种事务的总代价最小。
必须强调的是,聚簇只能提高某些应用的性能,而且建立与维护聚簇的开销是相当大的。对已有关系建立聚簇,将导致关系中元祖移动其物理存储位置,并使此关系上原有 的索引无效,必须重建。当一个元祖的聚簇码值改变时,该元组的存储位置也要做相应移动,聚簇码值要相对稳定,以减少修改聚簇码值所引起的维护开销。
因此,当通过聚簇码进行访问或连接是该关系的主要应用,与聚簇码无关的其他访问很少或者是次要的,这时可以使用聚簇。尤其当 SQL 语句中包含有与聚簇码有关的 ORDER BY,GROUP BY,UNION,DISTINCT 等子句或短语时,使用聚簇特别有利,可以省去对结果集的排序操作;否则很可能会适得其反。
HASH 存取方法的选择
有些数据库管理系统提供了 HASH 存取方法。选择 HASH 存取方法的规则如下:
如果一个关系的属性主要出现在等值连接条件中或主要出现在相等比较选择条件中,而且满足下列两个条件之一,则此关系可以选择 HASH 存取方法:
- 如果一个关系的大小可预知,而且不便;
- 如果关系的大小动态变化,而且数据库管理系统提供了动态 HASH 存取方法。
物理存储结构设计
物理存储结构设计的目的
是确定如何在磁盘存储器上存储关系、索引和聚簇,使得空间利用率最大化,数据操作引起的系统开销最小化。确定数据库物理结构
主要
指确定数据的存放位置和存储结构,包括:确定关系、索引、聚簇、日志、备份等的存储安排和存储结构,确定系统配置等。
确定数据的存放位置和存储结构要综合考虑存取时间、存储空间利用率和维护代价 3 个方面的因素。这 3 个方面常常是相互矛盾的,因而需要进行权衡,选择一个折中方案。
确定数据的存放位置:
为了提高系统性能,应该根据应用情况将数据的易变部分,经常存取部分和存取效率低部分分开存放。
例如,目前许多计算机有多个磁盘或磁盘阵列,因此可以将表和索引放在不同的磁盘上,在查询时,由于磁盘驱动器并行工作,可以提高物理 I/O 读写的效率;也可以将比较大 的表分放在两个磁盘上,以加快存取速度,这在多用户环境下特别有效;还可以将日志文件与数据库对象(表、索引等)放在不同的磁盘上,以改进系统的性能。
由于各个系统所能提供的对数据进行物理安排的手段、方法差异很大,因此设计人员应子了解给定的 RDBMS 提供的方法和参数,针对应用环境的要求,对数据进行适当的物理 安排。
确定系统配置:
DBMS 产品一般都提供了一些系统配置变量、存储分配参数,供设计人员和 DBA 对数据库进行物理优化。初始情况下,系统都为这些变量赋予合理的默认值。但是这些值不一定 适合每一种应用环境,在进行物理设计时,需要重新对这些变量赋值,以改善系统的性能。
系统配置变量很多,例如,同时使用数据库的用户数,同时打开的数据库对象数,内存分配参数,缓冲区分配参数(使用的缓冲区长度、个数),存储分配参数,物理块的大小, 物理装填因子,时间片大小,数据库的大小,锁的数目等。这些参数影响存取时间和存储空间的分配,在物理设计时就要根据应用环境满足这些参数值,以使系统性能最佳。
在物理设计时对系统配置变量的调整只是初步的,在系统运行时还要根据系统实际运行情况做进一步的调整,以期切实改进系统性能。
磁盘空间管理:
由于物理存储结构的设计包含的方面非常广泛,而且不同的数据库管理系统对磁盘空间管理的策略差别很大,所以下面以分区的设计来简单介绍物理存储结构设计。
数据库系统一般有多个磁盘驱动器,有些系统还带有磁盘阵列。数据在多个磁盘组上的分布也是数据库物理设计的内容之一,这就是所谓分区设计
。下面是分区设计的
一般原则。
- 减少访盘冲突,提高 I/O 的并行性
多个事务并发访问统一磁盘组时,会因访盘冲突而等待。如果事务访问的数据分布在不同的磁盘组上,则可并行地执行 I/O,从而提高数据库的效率。从减少访盘冲突、提高 I/O 并行性的观点来看,一个关系最好不要放在一个磁盘组上。而是水平分割成多个部分,分布到多个磁盘组上。分割在表面上看似乎与聚集是矛盾的,实际上聚集是把聚集 (聚簇)属性相同的元组在同一磁盘上存放,以减少 I/O 次数;分割是将整个关系分布到不同的磁盘组上,利用并行 I/O 提高性能。然而两者是相辅相成的。分割的策略决定 与查询的特征,可以按属性值分割,也可以不按属性值分割,例如按元组的输入次序轮流存放到各个磁盘组上。
- 分散热点数据,均衡 I/O 负责
实践证明,数据库中的数据被访问的频率是很不均与的。经常访问的数据,称为热点数据
。热点数据最好分散存放在各个磁盘组上,以均衡各个磁盘组的负荷,充分
发挥多个磁盘组并行操作的优势。
- 保证关键数据的快速访问,缓解系统的瓶颈
在数据库系统中,有些数据,例如数据目录,是每次访问的“必经之地”。其访问速度影响整个系统的性能。还有些数据从应用的必须来说,对性能的要求特别高,例如某些 实时控制数据,这些数据要优先分配到快速磁盘上。有时甚至为减少访盘冲突,宁可闲置一些存储空间,将某一磁盘组供其专用。
ORACLE 磁盘空间管理方法:
ORACLE 中的最基本数据单位是存储记录。存储记录
是与一个关系元组有关的数据项集合,除了用户数据以外,存储记录还包括必要的指针、记录长度和其他的系统所
需要的管理信息。物理存储块
是磁盘读写的基本单位。每个物理存储块可以存储多个记录。由一个或多个连续的物理存储块组成的存储空间称为数据域
。
与关系、索引、聚集等数据库对象相对应的存储结构称为数据段
,由一个或多个数据域构成。构成数据段的数据域可以具有相同或不同的长度。
数据段存储在数据库文件中。
一个数据库文件
可以包含多个数据快中的数据。一个数据段可以属于多个数据库文件。一个数据库文件对应一个操作系统文件。一个或多个数据库文件形成一个数据库分区
。
数据库分区是物理数据库的逻辑划分。一个物理数据库
可以包括一个或多个数据库分区。一个数据库分区只能属于一个物理数据库。
评价物理设计与性能预测
数据库物理设计过程中想哟啊对时间效率、空间效率、维护代价和用户要求进行权衡,其结果可以产生某种方案。数据库设计人员必须对这些方案进行细致的评价,从中选择 一个较优的方案作为数据库的物理结构。
评价物理数据库的方法完全依赖于所选用的 DBMS,主要是从定量估算各种方案的存储空间、存取时间和维护代价入手,对估算结果进行权衡、比较,选择出一个较优的合理的 物理结构。如果该结构不符合用户需求,则需要修改设计。
估算代价是非常复杂的,目前数据库物理设计主要还是采用启发式的方法,即根据一般的原则和设计要求,运用 DBMS 提供的各种手段,设计出初步方案,通过基准程序测试 进行调整。
评价物理结构设计完全依赖于具体的 DBMS,主要考虑操作开销,即为使用户获得及时、准确的数据所需的开销和计算机的资源开销。具体可分为以下几类:
- 查询和响应时间:
响应时间
是从查询开始到查询结果开始显示锁经历的时间。一个设计得好的应用程序可以减少 CPU 时间和 I/O 时间。
- 更新事务的开销:
主要是修改索引、重写物理块或问价,以及写校验等方面的开销。
- 生成报告的开销:
主要包括索引、重组、排序和显示结果的开销。
- 主存储空间的开销:
包括程序和数据所占用的空间。一般对数据库设计者来说,可以对缓冲区做适当的控制,包括控制缓冲区个数和大小。
- 辅助存储空间的开销:
辅助存储空间分为数据块和索引块两种,设计者可以控制索引块的大小、索引块的充满度等。
实际上,数据块设计者只能对 I/O 服务和辅助空间进行有效控制。对于其他的方面则只能进行有限的控制或者根本不能控制。
数据库实施与维护
数据库的物理设计完成之后,既可以进入数据库的实施阶段,设计人员用 DBMS 提供的数据定义语言和其他应用程序将数据库逻辑设计和物理设计结果严格描述出来, 称为 DBMS 可以接受的源代码,再经过调试产生目标模式,然后就可以组织数据入库了。数据库实施阶段的两项重要工作就是数据的载入和应用程序的编码与调试。
数据库实施
根据数据库的逻辑设计和物理设计结果,在计算机系统上建立实际的数据库结构装入数据、进行测试和试运行的过程称为数据库的实施
。
- 建立实际数据库结构
用护体的数据库管理系统提供的数据定义语言把数据库逻辑设计和物理设计的结果严格描述出来,作为 DBMS 可以接受的源模式,通过 DBMS 编译成目标模式,执行之后 实际的数据库结构就建立起来了。
- 装入实验数据,调试应用程序
实验数据可以是实际的数据,也可以是随机的数据。但测试数据应尽可能充分反映现实世界的各种情况,这样才能确定应用程序的功能是否满足设计要求。
- 装入实际数据
数据库系统的数据量通常都很大,所以,一般都是通过系统提供的使用程序或专门的录入程序来完成装入数据的工作。其实,在装入数据之前往往还有大量的数据整理工作。 这是由于数据库作为共享资源,面对的是不同的用户、不同的应用,因此数据来自各个方面,难免在数据的结构、格式与新设计的数据库系统有相当的差距。
- 进入试运行
当有部分数据装入数据库以后,就可以对数据库系统进行联调,这个过程称为数据库的试运行
。在试运行阶段,除了对应用程序做进一步调试之外,重点是执行对
数据库的各种操作,实际测量系统的性能指标,检查是否达到设计要求。若发现问题,则应回过来修改物理结构、甚至修改逻辑结构。
数据加载
数据是数据库系统最基础最重要的资源。数据加载
是在数据库结构建立后,将试运行数据或实际运行数据载入数据库的过程。数据加载是数据库实施阶段最主要的
工作。
数据加载的准备
数据加载前的准备工作是十分重要的数据库系统建设的基础工作。数据的可靠和正确是数据库系统应用的基本要求,“进去是一堆垃圾,出来还是一堆垃圾”是对数据库系统 建设的重要警训。
由于数据库存储的数据量一般都很大,且分散在众多的组织和部门中的各种文件和凭证上,还有可能提前准备和进行必要的转换。数据的准备和转换工作细致且繁杂,是 一项十分机械且耗费时间和人力的工作,必须制定详细的极化和时间表,并进行数据加载前的组织工作和人员培训。
数据加载的方法
数据的加载有两种不同的形式:一种是数据的手工录入和加载
,即从原始的凭证上录入相应数据,经验检查合格后写入数据库;另一种是已经存放在文件系统或原有
数据库中的数据,需要进行转换。转换的方法也有两种:一种是数据库管理系统已经提供必要的转换手段,即有转换程序,可利用转换程序进行数据的转换;另一种是需要
数据库管理员自己编织转换程序来实现数据的转换。而后一种可能是经常使用的方法。
数据输入的自动化方法编制好或由系统提供输入程序,其主要功能包括:原始数据的输入、抽取、校验、分类、转换和综合,最后提供符合数据库结构要求且正确无误的数据, 并把这些数据存入数据库中。输入程序可能是一类复杂的程序,因为其适应的数据种类和应完成的任务较为繁杂,需要编写许多应用程序才能完成任务。且输入程序的设计 还必须在数据库物理设计时开始着手进行,即进行并行开发,这样才能相互配合,并能及时开始输入工作。
数据加载正确性保证
由于要如可的数据在原来系统中的格式结构与新系统中的不完全一样,有的差别可能还比较大,不仅向计算机内输入数据时发生错误,转换过程也有可能出错。因此在源 数据入库之前要采用多种方法对它们进行正确性检查,以防止不正确的数据入库,这部分的工作在整个数据输入子系统中是非常重要的。当然,不同的数据对象应有不同 的检查力度。有的数据应在输入过程中进行多次检查,每次检查所采用的方法和检查的重点是不相同的,这样才能尽可能地保证入库后的正确性和可用性。
数据加载的正确性是保证数据库数据正确的重要措施,也是最基础性的工作,一旦数据垃圾进入数据库中,则以后的数据加工都将毫无意义。
另外,在设计数据输入子系统时还要注意原有系统的特点。例如对于原有系统是人工数据处理系统的情况,尽管新系统的数据结构可能与原系统有很大差别,在设计数据
输入子系统时,还是要金陵让用户以原系统结构相近的形式输入源数据,这不仅可使用户鞥呢方便地处理手工文件,更重要的是能减少用户出错的机会,保证数据输入的
质量。现有的 DBMS 一般都提供将市场上比较流行的 DBMS 产品的数据转换到本系统的工具,对于原有系统是数据库系统的情况,就可以利用新系统数据库的数据转换工具
,
先将原系统中的表转换到新系统中相同结构的临时表中,再将这些表中的数据分类、转换、综合成符合新系统中数据结构的数据,然后插入到新系统相应的表中。
在数据库结构设计过程中,对数据库应用程序的设计是同时进行的,因此在组织数据入库的同时还要调试应用程序。
程序排错方法
程序排错是程序测试后开始的工作,它确定测试中锁发现错误的性质和位置并修改错误。排错方法有多种,但在理论和方法上还不成熟。
简单排错法
人工转储、打印并人工检查、确定错误的性质和位置。借助排错工具,插入打印语句,设置断点,跟踪语句的执行,确定程序执行正确与否。简单排错方法属于类排错方法, 其有效性较低,且依赖于测试人员的经验和水平。
归纳排错法
从特殊到一般的归纳对问题进行分析和思考,其过程可归纳为:通过实例运行结果,寻找线索,从线索(一个或多个测试实例的执行结果所反映的错误征兆)和线索之间 的联系出发作归纳分析,从而确定错误。其步骤可归纳如下:
- 寻找适当数据:
通过实例运行,查找与错误征兆有关的信息,并集中为线索。主要内容是列出程序已经正确做了什么的全部信息。
- 组织数据:
列出错误征兆数据结构,如可列出表格。表中记载的信息包括:列出错误征兆、观察到征兆的位置、发生征兆的时间、征兆的范围和数量。
- 研究线索,给出猜想:
利用线索及线索间的关系,给出一个或多个引起错误的猜想。
- 证明猜想:
将猜想线索做分析对比。使全部的错误征兆和线索都得到解释,否则猜想失败。
演绎排错法
从一般推测触发,使用逐步求精方法去获得错误的性质和位置,其步骤可归纳为:
- 列出猜测构造数据:
写出全部想到的原因/推测,它们可能是不完全的、是猜测性的,通过猜测收集构造有用数据。
- 清除原因:
通过已有数据的分析,寻找矛盾,消除全部可能的原因,若全清除,则需要考虑新的原因,设计和运行新的测试。若还剩有未消除原因,则选择可能性最大的原因。
- 原因求精:
定义和完善未清除原因,做定义和补充、求精。
反向搜索排错法
或称回溯法
,从程序产生不争取的结果出,沿逻辑路径反向搜索,知道发现程序错误为止。
测试拍错发
从测试实例发现的错误征兆出发,对实例做某些修改,再做测试,通过两次测试结果比价,通常可找到有用的排错信息。
在确定错误的性质和位置时,应考虑到某些心理因素和吸收必要的经验,以利于提高工作效率和质量。
- 通过思考分析错误征兆可找出大部分产生的原因;
- 当遇到难以立即解决的困难时,应立即停止,从而使自己走出困境;
- 分析错误产生的原因时可以采用工具,但工具必须配合思考才能有效;
- 盲目的试验对于发现错误是作用不大的。
以上这些经验在进行程序拍错时可以借鉴。
在修改已经发现的错误时可参考以下经验:
- 错误往往具有密集性,当在某程序段出现了错误时应注意邻近搜索;
- 修改错误时是修改错误而不应是修改征兆;
- 修改后的程序还可能出错,必须进行回归测试;
- 应该修改源代码而不是修改目标代码;
- 错误修改本身也是编码,应使用可用的程序设计方法。
测试与排错的关系
测试与排错是相互联系但又是性质和目的不同的两类活动,它们之间存在差别,了解和区别这种差别有利于对程序进行整体的调试。
- 实施的时间不同:
测试应在排错之前进行,排错一般只有在发现错误征兆后才能有效地进行;
- 根本目的不同:
测试的根本目的是证明程序存在错误,而排错是将错误的程序修改成正确的程序;测试的目的主要是去揭露程序中隐含的错误,而排错则是去改正程序中已发现的错误。
- 出发条件不同:
测试是从已知条件出发,使用预定的方法,并有事先期望的测试结果,但其结果是不可预测的。而排错则是从未知初始条件出发,即在错误的性质、位置和范围未知的 情况下进行,其结果亦不可预测。
- 安排计划不同:
测试可以事先安排计划,指定日程表,使其按计划进行,而排错的方法、时间和结果都难以事先确定。
- 性质不同:
测试的性质有些类似于程序正确性证明,而排错的方法是基于推理和归纳的。
-
测试的进行是一种严格的、机械的且是强制性的方法和过程,一般其结果是可以预测的。
-
行为人不同:
一般的测试可以也应该由专门的测试人员来完成,而排错一般则要依靠程序人员来完成。
- 完善性不同:
软件测试已经建立了较完整的方法和理论,而排错则具有很大的任意性,在很大程度上还要依靠程序人员的经验、个人的能力和认真态度。
了解程序测试与程序拍错的关系和区别,将有利于程序正确性保证措施的实施,即计划的指定和人员的组织,切实和有效地提高程序的质量。
数据库试运行
将原有系统的一小部分数据输入数据库后,就可以开始对数据库系统进行联合调试了,这称为数据库的试运行
,数据库的试运行是数据库正式运行前必须完成的工作。
数据库试运行的准备
建立数据库结构后,由数据录入和转换程序将数据加载到数据库中,并建立起对数据进行加工的应用程序。有了数据和程序的准备,数据库系统才能具备试运行的条件。
数据库试运行的任务
数据库在试运行阶段应实施的工作内容包括:
- 运行应用程序,执行数据库的各种操作,进一步验证和测试应用程序的功能。
- 做数据库应用系统的性能测试,分析是否达到在数据库物理设计中所预测的性能指标。
前者为综合性地在试运行中对系统的功能做进一步的验证;后者更着重性能指标的验证,要通过系统的试运行分析系统在总体上是否达到了设计要求。
试运行的结果经分析和总结后,可能有两种结果:一种是符合设计要求,另一种是不完全符合设计要求,特别是性能指标的要求。若是后者则必须回到屋里设计阶段进行 修改,如调整物理结构、修改系统参数等,有时甚至返回到逻辑设计阶段,即调整逻辑结构。
上述情况之所以会产生的原因,往往是在性能预测中,会对实际可能产生的复杂情况难以事先准确估计,一般只是近似的估计或在估计中忽略了某些看来是次要的因素, 致使其粗糙和失真,与实际系统运行相比存在一定的差距,要避免上述可能的失误,经验是十分重要的。
数据库试运行的实施
数据库试运行是为数据库运行提供条件,发现和改进系统,并使系统达到可运行的水平。其实施方式可以是满负荷运行,即数据全部加载后试运行,也可以是分期分批输入 数据,先输入小批量数据做调试用,待运行负荷要求后再大批量输入数据,逐步增加数据量,最后加载全部数据。后者是常采用的方法。由于数据库系统的建立,特别是 大型复杂的数据库系统的建立,包括试运行都是一项复杂的工作,即使是试运行也可能有反复,而不能一次成功。试运行期间可能出现的问题是多样的。诸如,软件和硬件 的错误,操作的错误等,为了保证试运行的进行,必须做好数据库的转储以利于恢复。
在数据库试运行阶段,由于系统还不稳定,硬、软件故障随时都可能发生。而系统的操作人员对新系统还不熟悉,误操作也不可避免,因此应首先调试运行 DBMS 的恢复 功能,一旦故障发生,能使数据库尽快恢复,尽量减少对数据库的破坏。
数据库运行与维护
数据库试运行合格后,数据库开发工作就基本完成,即可投入正式运行了。但是,由于应用环境在不断变化,数据库运行过程中物理存储也会不断变化。对数据库设计进行 评价、调整、修改等维护工作是一个长期的任务,也是设计工作的继续和提高。
在数据库运行阶段,对数据库经常性的维护工作主要是由 DBA 来完成的,它包括:
- 数据库的转储和恢复
- 数据库的安全性、完整性控制:
在数据库运行过程中,由于应用环境的变化,对安全性的要求也会发生变化,加入有的数据原来是机密的,现在是可以公开查询了,而新加入的数据又可能是机密了。而 系统中用户的密级也会改变。这些都需要 DBA 根据实际情况修改原有的安全性控制。同样,数据库的完整性约束条件也会变化,也需要 DBA 不断修正,以满足用户要求。
- 数据库性能的监督、分析和改进:
在数据库运行过程中,监督系统运行,对检测数据进行分析,找出改进系统性能的方法是 DBA 的又一重要任务。目前有些 DBMS 产品提供了检测系统性能参数的工具,DBA 可以利用这些工具方便地得到系统运行过程中一系列性能参数的值,DBA 应仔细分析这些数据,判断当前系统运行状况是否是最佳,应当做哪些改进,例如调整系统物理 参数,或对数据库进行重组织或重构等。
- 数据库的重组织与重构造:
关系数据理论
针对一个具体问题,应该如何构造一个适合于它的数据模式,即应该构造几个关系模式,每个关系由哪些属性组成等。这是数据库设计的问题,确切地讲是数据库逻辑设计
问题。
实际上设计任何一种数据库应用系统,不论是层次的、网状的还是关系的,都会遇到如何构造合适的数据模式即逻辑结构的问题。由于关系模型有严格的数学理论基础,
并且可以向别的数据模型转换,因此,人们就以关系模型为背景来讨论这个问题,形成了数据库逻辑设计的一个有力工具—关系数据库的规范化理论
。规范化理论
虽然是以关系模型为背景,但是它对于一般的数据库逻辑设计同样具有理论上的意义。
非规范化关系模式的问题
关系数据库是由一组关系组成的,所以关系数据库的设计归根到底是如何构造关系,即如何把具体的客观事物划分为几个关系,而每个关系又由哪些属性组成。在我们构造 关系时,经常会发现数据冗余和更新异常等现象,这是由关系中各属性之间的相互依赖性和独立性造成的。
关系模型的形式化定义
一个关系模式应当是一个五元组:
R(U,D,DOM,F)
这里:
- 关系名 R,它是符号化的元组定义;
- 一组属性 U;
- 属性组 U 中属性锁来自的域 D;
- 属性到域的映射 DOM;
- 属性组 U 上的一组数据依赖 F。
由于第3、4点对模式设计关系不大,因此可暂且把关系模式看作是一个三元组:
R<U,F>
当且仅当 U 上的一个关系 r 满足 F 时,r 称为关系模式 R<U,F>
的一个关系。
关系作为一张二维表,对他有一个最起码的要求:每一个分量必须是不可分的数据项。满足了这个条件的关系模式就属于第一范式(1NF)
。
在模式设计中,面对同一个问题具有多个解决方案和模式设计,哪个“更好”呢?这属于函数依赖
和规范化
问题。
非规范化造成的问题
但是,这个关系模式存在以下问题:
- 数据冗余太大:
比如,每一个系主任姓名重复出现,重复次数与该系所有学生的所有可能成绩出现次数相同,如表 6.1 所示。这将浪费大量的存储空间。
- 更新异常:
由于数据冗余,当更新数据库中的数据时,系统要付出很大的代价来维护数据库的完整性,否则会面临数据不一致的危险。比如,某系更换系主任后,必须修改与该系学生 有关的每一个元组。
- 插入异常:
如果一个系刚成立,尚无学生,就无法把这个系及其系主任的信息存入数据库。
- 删除异常:
如果某个系的学生全部毕业了,在删除该系学生信息的同时,把这个系及其主任的信息也丢掉了。
鉴于存在以上种种问题,我们可以得出这样的结论:Student 模式不是一个好的模式。一个“好”的模式应当不会发生插入异常、删除异常、更新异常,数据冗余应尽可能少。
要想设计一个“好”模式就需要规范化理论
支持。
问题的根源
- 完全依赖与部分依赖:
- 传递依赖:
函数依赖
为了便于了解函数依赖的概念,先看一个具体的关系实例。
函数依赖的严格定义:
关系的键码
之前说过键码的概念,本节从函数依赖的角度给出严格的定义。
键码定义:
键码的确定过程:
超键妈
函数依赖规则
三个函数依赖规则:
- 分解/合并规则:
- 平凡依赖规则:
- 传递规则:
计算属性的封闭集(或闭包)
计算过程:
例子:
规范化
关系数据库理论的意图是消除数据库中发生的异常。而规范化是消除异常的有效方法。
范式
- 第一范式:
- 第二范式:
概念解读例子:
模式分解:
分解实例:
一个关系模式 R 不属于 2NF,就会产生插入、删除异常,修改复杂等问题。
- 第三范式:
例 1:
例 2:
一个关系模式 R 不属于 3NF,就会产生插入、删除异常,修改复杂等问题。
- BC 范式(BCNF)
例子:
小结:
由 BCNF 的定义可以得到结论,一个满足 BCNF 的关系模式有:
- 所有非主属性对每一个码都是完全函数依赖;
- 所有的主属性对每一个不包含它的码,也是完全函数依赖;
- 没有任何属性完全函数依赖于非码的任何一组属性。
3NF 和 BCNF 是在函数依赖的条件下对模式分解所能达到的分离程度的测度。一个模式中的关系模式如果都属于 BCNF,那么在函数依赖范畴内,它已实现了彻底的 分离,已消除了插入和删除的异常。3NF 的“不彻底”表现在可能存在主属性对码的部分依赖和传递依赖。
分解的原则
模式分解例子:
模式分解的两个原则:
从上面例子可以看出,对模式的分解显然不是随意的。主要涉及两个原则:
- 无损连接:
- 保持依赖:
所以,在实际应用中,对模式分解的要求并不一定要达到 BC 范式,有时达到第三范式就足够了。
分解的方法
模式分级的两个规则:
- 公共属性共享:
- 相关属性合一:
模式分解的三种方法:
- 方法一:部分依赖归子集;完全依赖随键码
例子:
- 方法二:基本依赖为基础,中间属性做桥梁
- 方法三:找违例自成一体,舍其右全集归一;若发现仍有违例,再回首如法炮制
模式分解为 BC 范式的方法:
例子:
小结:
关系模式规范化小结
多值依赖
属性独立性带来的冗余
多值依赖的定义
定义:
例子:
第四范式
如果把多值依赖用于新的关系分解算法中,那么由多值依赖引起的冗余是可以清除的。在第四范式(4NF)里,随着违背 BC 范式的所有函数依赖的清除,所有的 “非平凡”多值依赖也都清除了。
定义:
定义解读实例:
分解成第四范式
例子:
小结:
第五范式
当实体是第四范式的并且在实体的候选码中没有连接依赖时,此实体就是第五范式
(也叫做工程连接范式)的。
当我们使用规范化规则分解实体时,应该能够重新构造原始实体。重构造的实体应该保持连接以保证无数据丢失和不产生多余的(往往是不正确的)数据,就叫做
无损连接
。
如果一个实体不能被分解成更小的几个实体,而且每个实体有不丢失数据的、来自原始实体的不同码,则此实体就是第五范式的实体。如果数据在分解后丢失了,则 就不可能是无损连接,如果所有被分解的实体使用原始实体中的某个候选码作为其码,那么这些实体的连接后的结果是一个无损连接。
注意:
第三范式之上的范式在很大程度上是理论上研究的问题,作为实践,第三范式是产品数据库的规范化的终点。
【注意】本文属于作者原创,欢迎转载!转载时请注明以下内容:
(转载自)ShengChangJian's Blog编程技术文章地址:
https://ShengChangJian.github.io/2016/12/dataBase-basic.html
主页地址:https://shengchangjian.github.io/