数据库设计

数据库设计是指对于一个给定的应用环境,构造优化的数据库逻辑模式和物理结构,并据此建立数据库及其应用系统,使之能够有效地存储和管理数据,满足用户的各种信息管理需求和数据操作需求。

数据库设计概述

数据库设计的核心目标

数据库设计的目标是为用户和各种应用系统提供一个坚实的信息基础设施和高效的运行环境。一个高效率的运行环境主要体现在:

  • 数据存取效率高:快速查询、更新数据。
  • 数据存储空间利用率高:减少数据冗余,节省存储成本。
  • 数据库系统运行管理效率高:便于维护、备份、恢复等。

数据库设计的特点

  1. 综合性任务:俗话说「三分技术,七分管理,十二分基础数据」。数据库建设不仅是技术选型和实现,更涉及到项目管理、业务流程梳理以及高质量基础数据的持续收集、整理和更新。

  2. 结构设计与行为设计并重

    • 早期的数据库设计偏重于为新系统建立文件,更侧重于程序设计,容易导致数据冗余和不一致。
    • 传统软件工程方法往往重行为设计(功能实现),数据结构设计相对滞后。
    • 现代数据库设计强调将数据库的结构设计(存储什么数据,数据间关系如何)和行为设计(对数据进行何种操作,操作流程如何)紧密结合,从系统整体角度进行优化。
    graph LR
        A[现实世界] --> B(数据分析)
        A --> C(功能分析)
    
        subgraph "数据库设计(结构)"
            direction LR
            B --> D[概念模型设计]
            D --> E[逻辑数据库设计]
            E --> F[物理数据库设计]
            F --> G[子模式设计]
            G --> H[建立数据库]
        end
    
        subgraph "应用系统设计(行为)"
            direction LR
            C --> I[功能模型/说明]
            I --> J[事务设计]
            J --> K[应用设计]
            K --> L[应用开发]
            L --> M[系统调试]
        end
        H <-.-> M

数据库设计方法论

  • 手工试凑法:早期方法,依赖设计人员的经验和水平,缺乏科学理论指导,设计质量难以保证,后期维护代价高。
  • 规范设计法:基于一套规范的理论和方法(如 E-R 模型、范式理论、面向对象方法、UML 等),通过迭代和逐步求精的方式进行设计,是现代数据库设计的主流。

数据库设计的基本步骤

数据库设计通常分为以下六个阶段,构成一个完整的设计生命周期:

graph TD
    A[1\. 需求分析] --> B[2\. 概念结构设计]
    B --> C[3\. 逻辑结构设计]
    C --> D[4\. 物理结构设计]
    D --> E[5\. 数据库实施]
    E --> F[6\. 数据库运行和维护]

    A -- 独立于具体 DBMS --> B
    C -- 与选用 DBMS 密切相关 --> D
  1. 需求分析阶段:准确收集和分析用户的数据需求和功能需求。此阶段独立于任何具体的数据库管理系统(DBMS)
  2. 概念结构设计阶段:将用户需求抽象为独立于具体 DBMS 的概念模型(如 E-R 图)。此阶段也独立于任何具体的 DBMS
  3. 逻辑结构设计阶段:将概念模型转换为特定 DBMS 支持的数据模型(如关系模型),并进行优化。此阶段与选用的 DBMS 密切相关
  4. 物理结构设计阶段:为逻辑数据模型选择合适的物理存储结构和存取方法。此阶段与选用的 DBMS 密切相关
  5. 数据库实施阶段:根据逻辑设计和物理设计的结果,建立数据库,编写和调试应用程序,组织数据入库并进行试运行。
  6. 数据库运行和维护阶段:数据库投入正式运行后,进行持续的性能监控、备份恢复、安全管理、数据重组等维护工作。

参与数据库设计的人员

  • 系统分析人员数据库设计人员:核心角色,贯穿设计始终,其水平直接影响数据库系统质量。
  • 数据库管理员(DBA)和用户代表:主要参与需求分析、数据库运行和维护阶段,确保系统满足用户实际需求。
  • 应用开发人员(程序员、操作员):主要在实施阶段参与,负责编制应用程序和准备软硬件环境。

数据库设计过程中的各级模式

数据库的设计过程与数据库系统的三级模式结构(外模式、概念模式、内模式)紧密相关:

graph TD
    subgraph 用户需求层面
        U1[应用需求 1]
        U2[应用需求 2]
        U3[应用需求 3]
        U4[应用需求 4]
    end

    subgraph 概念层
        CM[概念模式(E-R 图)]
    end

    subgraph 逻辑层
        LM[逻辑模式(如关系模式)]
        V1[外模式/视图 1 for 应用 1]
        V2[外模式/视图 2 for 应用 2]
        V3[外模式/视图 3 for 应用 3]
        V4[外模式/视图 4 for 应用 4]
    end

    subgraph 物理层
        IM[内模式(存储结构, 索引)]
    end

    U1 -- 综合 --> CM
    U2 -- 综合 --> CM
    U3 -- 综合 --> CM
    U4 -- 综合 --> CM

    CM -- 转换为特定 DBMS 支持的模型 --> LM

    LM -- 定义 --> V1
    LM -- 定义 --> V2
    LM -- 定义 --> V3
    LM -- 定义 --> V4

    LM -- 映射为物理存储 --> IM

    style CM fill:#lightgreen
    style LM fill:#lightblue
    style IM fill:#lightcoral
    style V1 fill:#lightyellow
    style V2 fill:#lightyellow
    style V3 fill:#lightyellow
    style V4 fill:#lightyellow
  • 需求分析阶段:综合各个用户的应用需求,形成对现实世界信息需求的初步理解。
  • 概念设计阶段:基于用户需求,设计出独立于机器特点和具体 DBMS 产品的概念模式,常用 E-R 图表示。
  • 逻辑设计阶段
    1. 将 E-R 图转换为特定 DBMS 支持的数据模型(如关系模型),形成数据库的逻辑模式(基本表)。
    2. 根据用户处理要求和安全性考虑,在基本表基础上建立必要的外模式(视图)。
  • 物理设计阶段:根据 DBMS 特点和处理需求,进行物理存储安排,建立索引等,形成数据库的内模式

需求分析

需求分析是数据库设计的起点,其结果的准确性直接影响后续设计阶段的质量和最终系统的实用性。

需求分析的核心任务

  1. 详细调查现实世界处理对象:如组织结构、部门职能、企业业务等。
  2. 充分了解原系统工作概况:无论是手工系统还是已有的计算机系统。
  3. 明确用户的各种需求
    • 信息要求:用户希望从数据库中获取什么信息?这些信息导出数据库需要存储哪些数据?
    • 处理要求:用户需要完成哪些处理功能?对处理性能(如响应时间、吞吐量)有何要求?
    • 安全性与完整性要求:数据的保密级别、访问控制、数据一致性约束等。
  4. 确定新系统的功能
  5. 充分考虑今后可能的扩充和改变:系统应具备良好的可扩展性。

确定用户最终需求的难点

  • 用户可能缺乏计算机知识,难以准确表达需求,且需求可能随理解深入而变化。
  • 设计人员可能缺乏用户领域的专业知识,不易理解用户的真实意图。
  • 解决方法:设计人员必须与用户进行持续、深入的交流和迭代,逐步明确实际需求。

需求分析的方法与步骤

  1. 调查用户需求的步骤
    1. 调查组织机构情况:了解部门组成、职责,为分析信息流程做准备。
    2. 调查各部门业务活动情况:了解数据输入、使用、加工、输出的流程和格式。
    3. 协助用户明确新系统要求:在熟悉业务基础上,明确信息、处理、完整性等要求。
    4. 确定新系统的边界:明确哪些功能由计算机完成,哪些仍由人工完成。
  2. 常用调查技巧
    • 跟班作业:亲身体验业务流程。
    • 开调查会/座谈:与用户群体交流。
    • 请专人介绍。
    • 针对性询问。
    • 设计调查表请用户填写。
    • 查阅相关记录和文档。
  3. 结构化分析方法(Structured Analysis, SA):
    • 一种自顶向下、逐层分解的分析方法,从系统组织机构入手分析系统。
    • 最终产出需求分析报告,需用户认可。

数据字典(Data Dictionary)

数据字典是关于数据库中数据的描述,即元数据(metadata),而不是数据本身。它在需求分析阶段建立,并在整个数据库设计过程中不断修改、充实和完善,是数据收集和分析的主要成果。

与 RDBMS 数据字典的区别

此处的需求分析阶段的数据字典是设计文档的一部分,描述了设计者对数据的理解和约定。而关系数据库管理系统(RDBMS)内部也有数据字典(系统目录),存储了数据库的实际元数据定义。两者概念相关但用途和阶段不同。

数据字典主要包含以下内容:

  1. 数据项(Data Item)
    • 定义:数据不可再分的最小组成单位。
    • 描述内容:数据项名、含义说明、别名、数据类型、长度、取值范围、取值含义、与其他数据项的逻辑关系(如完整性约束)、数据项之间的联系(可用函数依赖描述)。
    • 「取值范围」和「与其他数据项的逻辑关系」是设计数据检验功能和完整性约束的依据。
  2. 数据结构(Data Structure)
    • 定义:反映数据之间的组合关系。可由若干数据项、其他数据结构或两者混合组成。
    • 描述内容:数据结构名、含义说明、组成(包含的数据项或数据结构)。
  3. 数据流(Data Flow)
    • 定义:数据结构在系统内传输的路径。
    • 描述内容:数据流名、说明、数据流来源(来自哪个过程)、数据流去向(到哪个过程)、组成(数据结构)、平均流量、高峰期流量。
  4. 数据存储(Data Store)
    • 定义:数据结构停留或保存的地方,是数据流的来源和去向之一。
    • 描述内容:数据存储名、说明、编号、输入的数据流、输出的数据流、组成(数据结构)、数据量、存取频度、存取方式(批处理/联机,检索/更新,顺序/随机)。
  5. 处理过程(Process)
    • 定义:对数据流进行具体处理的逻辑单元。其具体逻辑常用判定表或判定树描述,数据字典中主要记录说明性信息。
    • 描述内容:处理过程名、说明、输入(数据流)、输出(数据流)、处理简要说明(功能、处理要求如频度、数据量、响应时间等)。处理要求是后续物理设计和性能评价的依据。

需求分析总结

  • 需求分析是数据库设计的基石,其产出(如数据字典)是后续概念设计的基础。
  • 设计人员应充分考虑系统的可扩展性和易维护性。
  • 用户的积极参与至关重要。

概念结构设计

概念结构设计的目标是将需求分析阶段得到的用户需求抽象为独立于具体 DBMS 的信息结构,即概念模型

概念模型

  • 特点
    1. 能真实、充分地反映现实世界。
    2. 易于理解,便于与不熟悉计算机的用户交流。
    3. 易于修改和扩充,适应需求变化。
    4. 易于向各种具体的数据模型(如关系模型、网状模型、层次模型)转换。
  • 常用工具E-R 模型(Entity-Relationship Model,实体-联系模型)及其扩展。

下面的 E-R 模型都是 Chen 式,即实体用矩形表示,属性用椭圆形表示,联系用菱形表示。属于比较古早的表示法。

现代的 E-R 模型通常使用 UML 类图来表示,实体用类(矩形)表示,属性用类的属性列表表示,联系用关联线表示。Mermaid 与 PlantUML 等工具都是用的这个。

E-R 模型基础

E-R 模型用一组基本概念来描述现实世界:

  • 实体(Entity):客观存在并可相互区别的事物,可以是具体的人、事、物,也可以是抽象的概念。如「学生」「课程」。
  • 属性(Attribute):实体所具有的某一特性。一个实体可由若干属性来刻画。如学生的「学号」「姓名」。
  • 联系(Relationship):实体内部的联系或实体之间的联系。如学生与课程之间的「选修」联系。

进一步的概念:

  • 实体型(Entity Type):用实体名及其属性名集合来抽象和刻画同类实体。如 学生(学号, 姓名, 性别)
  • 实体集(Entity Set):同一类型实体的集合。如所有学生的集合。
  • 码/关键字(Key/Identifier):唯一标识实体集中每个实体的属性或属性组。如「学号」是学生实体的码。

联系的类型

  1. 两个实体型之间的联系
    • 一对一联系(1:1):实体集 A 中每个实体至多与实体集 B 中一个实体有联系,反之亦然。
      • 例如:一个学生对应一个学籍档案,一个学籍档案也只对应一个学生(理想情况下)。
    • 一对多联系(1:n):实体集 A 中每个实体可与实体集 B 中多个实体有联系,而实体集 B 中每个实体至多与实体集 A 中一个实体有联系。
      • 例如:一个班级有多个学生,一个学生只属于一个班级。
    • 多对多联系(m:n):实体集 A 中每个实体可与实体集 B 中多个实体有联系,反之亦然。
      • 例如:一个学生可选修多门课程,一门课程可被多个学生选修。
  2. 多个实体型之间的联系:三个或更多实体型参与的联系。
    • 例如:「供应商」为「项目」供应「零件」。
  3. 单个实体型内部的联系:同一实体集内部各实体之间的联系。
    • 例如:职工实体型内部的「领导」与「被领导」的联系(通常是 1:n)。

联系的度(Degree of Relationship)

指参与一个联系的实体型的数目。

  • 二元联系:2 个实体型参与。
  • 三元联系:3 个实体型参与。
  • N 元联系:N 个实体型参与。

E-R 图表示法

  • 实体型:用矩形表示,矩形内写明实体名。
  • 属性:用椭圆形表示,椭圆形内写明属性名,并用无向边与对应实体型相连。
  • 联系:用菱形表示,菱形内写明联系名,并用无向边与相关实体型相连。在边旁标注联系的类型(1:1, 1:n, m:n)。
  • 联系的属性:如果联系本身也具有属性,则这些属性也用椭圆形表示,并与菱形相连。例如,「选修」联系可以有「成绩」属性。

扩展 E-R (EE-R) 模型

为了更丰富地表达现实世界的语义,E-R 模型进行了一些扩展:

  1. ISA 联系(泛化/特化,is a relationship)

    • 描述实体型之间的父类-子类关系。例如,「研究生」和「本科生」都是「学生」的子类。
    • 表示:用一个指向父类的三角形\triangle)连接父类和子类。
    • 特性
      • 子类继承父类的所有属性。
      • 子类可以有自己特有的属性(如研究生的「研究方向」,本科生的「高考总分」)。
    • 分类属性(Discriminator):父实体型中某个属性的值可以用来区分其实例属于哪个子类。该属性画在 ISA 三角形旁边。
    • ISA 约束
      • 不相交约束(Disjoint):父类中的一个实体不能同时属于多个子类实体集。在三角形中用 X 标记。
      • 可重叠约束(Overlapping):父类中的一个实体可以同时属于多个子类实体集。在三角形中用 o 标记,或无标记。
      • 完备性约束(Total Specialization/Generalization):父类中的每个实体都必须是某个子类的成员。连接父类与三角形的边用双线表示。
      • 部分约束(Partial Specialization/Generalization):父类中的实体可以不属于任何子类。连接父类与三角形的边用单线表示。
  2. 基数约束(Cardinality Constraints)

    • 更精确地描述一个实体在联系中出现的最少和最多次数。
    • 表示:在连接实体与联系的边上标注 (min, max) 对。*N 通常表示无上限。
      • (0,1):零个或一个。
      • (1,1):恰好一个。
      • (0,*)(0,N):零个或多个。
      • (1,*)(1,N):一个或多个。
    • 强制参与(Mandatory Participation):min >= 1,表示该实体型的每个实体都必须参与该联系。
    • 非强制参与(Optional Participation):min = 0,表示该实体型的实体可以不参与该联系。
    • 单值参与max = 1,表示该实体型的每个实体在该联系中至多出现一次。
    • 多值参与max = *,表示该实体型的每个实体在该联系中可以出现多次。
  3. 弱实体(Weak Entity)与识别联系(Identifying Relationship)

    • 弱实体型:一个实体型的存在依赖于另一个(标识性或属主)实体型的存在,且其自身属性不足以唯一标识其实例。例如,「家属」依赖于「职工」而存在,「房间」依赖于「大楼」而存在。
    • 识别联系:弱实体型通过其与标识性实体型的联系来获得唯一标识。
    • 表示
      • 弱实体型双线矩形
      • 识别联系双线菱形
      • 弱实体型的部分码(参与构成其完整标识的自身属性)通常用虚下划线标出。
    • 弱实体参与识别联系通常是强制的,并且联系通常是 1:n(一个强实体对应多个弱实体)。

概念结构设计策略

设计复杂系统的概念结构时,通常采用以下策略:

  1. 自顶向下(Top-down):首先定义全局概念结构的框架,然后逐步细化。从整体到局部。
  2. 自底向上(Bottom-up):首先定义各个局部应用(子系统)的概念结构,然后将它们集成起来,得到全局概念结构。从局部到整体。
  3. 逐步扩展(Inside-out/Incremental):首先定义最重要的核心概念结构,然后向外逐层扩充,像滚雪球一样逐步生成其他概念结构,直至形成总体概念结构。
  4. 混合策略(Hybrid):结合自顶向下和自底向上的优点。例如,先用自顶向下策略设计全局框架,再用自底向上策略设计各局部结构并集成到框架中。这是较常用的策略。
graph TD
    subgraph "混合策略"
        N1[全局需求] --> O1(全局框架)
        P1[局部需求 A] --> Q1(局部概念 A)
        P2[局部需求 B] --> Q2(局部概念 B)
        O1 & Q1 & Q2 --> R1[集成后的全局概念结构]
    end
    subgraph "逐步扩展"
        I1[核心需求] --> J1(核心概念结构)
        J1 -- 扩展 --> K1(扩展模块 1)
        K1 -- 扩展 --> L1(扩展模块 2)
        L1 --> M1[...全局概念结构]
    end
    subgraph "自底向上"
        direction BT
        E1[局部需求 1] --> F1(局部概念 1)
        E2[局部需求 2] --> F2(局部概念 2)
        F1 & F2 --> G1(集成)
        G1 --> H1[全局概念结构]
    end
    subgraph "自顶向下"
        A1[全局需求] --> B1(全局概念框架)
        B1 --> C1(子模块 1 概念)
        B1 --> C2(子模块 2 概念)
        C1 --> D1(...)
        C2 --> D2(...)
    end

实体与属性的划分原则

在概念设计中,一个现实世界的概念应该被设计为实体还是属性,需要仔细权衡。

  • 基本原则:为了简化 E-R 图,能作为属性对待的,尽量作为属性。
  • 划分准则
    1. 属性的独立性:作为属性,它本身不应再具有需要进一步描述的性质(即属性值应该是原子的或不可再分的,除非在 EE-R 模型中明确使用复合属性或多值属性)。一个属性不能包含其他属性。
      • 例如:「职工」的「职称」。如果「职称」仅仅是一个名称(如「工程师」),可以作为职工的属性。但如果不同的「职称」还关联着不同的「工资级别」「福利待遇」等需要描述的特性,那么「职称」就应该被设计为一个独立的实体。
    2. 属性的非联系性:属性不能与其他实体具有联系。E-R 图中表示的联系是实体与实体之间的。
      • 例如:「病人」的「病房号」。如果一个病人只住一个病房,且病房本身没有其他需要描述的属性或联系,那么「病房号」可以是病人的属性。但如果「病房」还需要与「医生」实体发生联系(如一个医生负责多个病房),那么「病房」就应该被设计为一个实体。

原子性说明

在传统的 E-R 模型中,属性要求是原子的。但在扩展 E-R 模型中,允许使用复合属性(如「地址」可由「省」「市」「街道」组成)和多值属性(如一个人的「电话号码」可以有多个),这些在后续逻辑设计时需要特殊处理。

E-R 图的集成

对于大型信息系统,通常会将其划分为若干子系统,分别设计各子系统的局部 E-R 图(分 E-R 图),然后再将它们集成起来,形成全局概念模型。

集成过程主要包括两步:

  1. 合并与冲突解决:将各个分 E-R 图合并起来,生成初步的全局 E-R 图。此过程中需要解决各分 E-R 图之间的冲突。
    • 属性冲突
      • 属性域冲突:同一属性在不同分图中类型、取值范围或取值集合不同。例如,「零件号」有的定义为整数,有的为字符型。解决方法:统一标准。
      • 属性取值单位冲突:例如,「重量」有的以公斤计,有的以斤计。解决方法:统一单位。
    • 命名冲突
      • 同名异义:不同意义的对象在不同分图中具有相同的名字。解决方法:为其中一些对象重新命名。
      • 异名同义:同一意义的对象在不同分图中具有不同的名字。例如,「科研项目」在财务科叫「项目」,在科研处叫「课题」。解决方法:统一命名。
    • 结构冲突
      • 同一对象抽象不同:例如,「职工」在一个分图中是实体,在另一个分图中是某个实体的属性。解决方法:根据全局视图和实体/属性划分原则,统一其抽象级别。
      • 同一实体属性不一致:不同分图中同一实体的属性个数或属性排列次序不同。解决方法:取各分图中属性的并集,并适当调整次序。
      • 实体间联系类型不同:例如,实体 E1 和 E2 在一个分图中是 m:n 联系,在另一个是 1:n 联系。解决方法:根据应用的全局语义进行综合或调整,通常以更一般或约束更弱的为准,或分析是否是不同角度的联系。
  2. 修改与重构(消除冗余):对初步的全局 E-R 图进行审查,消除不必要的冗余,生成最终的基本 E-R 图。
    • 冗余数据:指可由其他基本数据导出的数据。
    • 冗余联系:指可由其他联系导出的联系。
    • 消除方法
      • 分析法:依据数据字典中关于数据项之间逻辑关系的说明和数据流图来识别和消除冗余。
      • 规范化理论:运用函数依赖等理论进行分析(这是后续逻辑设计阶段的重点,但在概念阶段也可初步考虑)。

并非所有冗余都必须消除

有时为了提高查询效率,可能会有控制地保留某些冗余信息,但这需要仔细权衡,并确保有机制维护数据一致性。

通过以上步骤,可以设计出一个相对稳定、一致且能较好反映用户需求的全局概念模型。