软考-系统架构设计师 关系数据库详细讲解
个人博客:blogs.wurp.top
一、关系模型:理论基础
关系数据库的一切都建立在关系模型之上。
1. 核心概念
- 关系(Relation):对应一张二维表。
- 元组(Tuple):表中的一行,也称为记录。
- 属性(Attribute):表中的一列,也称为字段。每个属性有一个名称和数据类型。
- 域(Domain):属性的取值范围。例如,“性别”属性的域是{‘男’, ‘女’}。
- 候选码(Candidate Key):能唯一标识一个元组的属性或属性组。其值不能为空且不能重复。
- 主码(Primary Key):从候选码中选定的一个,作为该关系的唯一标识符。
- 外码(Foreign Key):关系R中的一个属性(组)是另一个关系S的主码,则该属性(组)是R的外码。用于建立表与表之间的关联。
2. 关系完整性约束(必考)
这是保证数据正确性和一致性的关键规则。
- 实体完整性:主码的值不能为空(NULL)。
- 参照完整性:外码的值必须等于被参照关系(S)中某个元组的主码值,或者为空(NULL)。
- 用户定义的完整性:针对具体应用设定的业务规则约束(如年龄必须大于0,薪水不能为负)。通常通过
CHECK
约束、触发器等方式实现。
二、关系代数:操作数据的理论基础
关系代数是一种抽象的查询语言,它通过对关系的运算来表达查询。它是理解SQL查询背后原理的关键。
1. 传统的集合运算(要求关系具有相同的目,即列数相同,且对应的属性域相同)
- 并(Union):
R ∪ S
,返回属于R或属于S的元组。 - 差(Difference):
R - S
,返回属于R但不属于S的元组。 - 交(Intersection):
R ∩ S
,返回既属于R又属于S的元组。 - 笛卡尔积(Cartesian Product):
R × S
,返回R中每个元组与S中每个元组连接后的新元组集合。目数是R与S的目数之和,元组数是两者元组数之积。
2. 专门的关系运算(核心)
- 选择(Selection):
σ_F(R)
,从关系R中选取满足给定条件F的元组。相当于SQL中的WHERE
子句。这是水平方向的操作。 - 投影(Projection):
π_A(R)
,从关系R中选出若干属性列A组成新的关系。相当于SQL中的SELECT
字段列表。这是垂直方向的操作。 - 连接(Join):
R ⋈ S
,从两个关系的笛卡尔积中选取属性间满足一定条件的元组。最常用的是等值连接和自然连接。- 等值连接:连接条件是属性间的相等比较。
- 自然连接:一种特殊的等值连接,它要求两个关系中进行比较的分量必须是同名的属性组,并且在结果中去掉重复的属性列。这是最常用的连接。
- 除(Division):
R ÷ S
,用于解决“包含了全部”类型的查询。例如,“查询选修了全部课程的学生”。
架构师视角:理解关系代数有助于理解查询优化器如何工作。一个复杂的SQL查询,最终会被查询优化器转换为一系列关系代数运算的高效执行计划。
三、结构化查询语言(SQL) - 实践工具
SQL是操作关系数据库的标准语言,是架构师必须精通的核心技能。
1. 数据定义语言(DDL)
CREATE TABLE
:创建表。必须熟练掌握定义主键、外键、各种约束(NOT NULL, UNIQUE, CHECK, DEFAULT)。ALTER TABLE
:修改表结构(增加列、修改列、删除约束等)。DROP TABLE
:删除表。
2. 数据操纵语言(DML) - 重中之重
SELECT
:查询的核心。- 基本结构:
SELECT ... FROM ... WHERE ...
- 高级功能:
DISTINCT
:去重。ORDER BY
:排序。GROUP BY
和HAVING
:分组和分组后过滤。WHERE
在分组前过滤行,HAVING
在分组后过滤组,这是重要区别。- 多表连接:
INNER JOIN
:内连接,只返回匹配的行。LEFT/RIGHT/FULL OUTER JOIN
:外连接,返回匹配的行,也返回一侧或两侧不匹配的行(用NULL填充)。
- 子查询(嵌套查询):查询中嵌套另一个查询。可以出现在
SELECT
、FROM
、WHERE
子句中。
- 基本结构:
INSERT
:插入数据。UPDATE
:更新数据。DELETE
:删除数据。
3. 数据控制语言(DCL)
GRANT
:授予用户权限。REVOKE
:收回用户权限。
4. 视图(View)
- 定义:基于一个或多个表(或视图)的虚拟表。视图不存储数据,其数据来自基表。
- 作用:
- 简化复杂查询:将复杂的查询定义为视图,用户可以直接查询视图。
- 逻辑数据独立性:基表结构改变时,可以通过修改视图来屏蔽变化,不影响应用程序。
- 安全性:只授予用户访问视图的权限,而不是基表,可以隐藏敏感数据。
四、数据库规范化(Normalization) - 设计高质量数据库
规范化的目的是消除数据冗余和插入/删除/更新异常,使数据库设计更合理。其核心是分析属性间的函数依赖。
- 第一范式(1NF):属性不可再分。即每个属性都是原子性的。这是关系模型的基本要求。
- 第二范式(2NF):在1NF基础上,消除非主属性对主码的“部分函数依赖”。
- 部分函数依赖:如果主码是复合主码,非主属性只依赖于主码的一部分,而不是全部。
- 第三范式(3NF):在2NF基础上,消除非主属性对主码的“传递函数依赖”。
- 传递函数依赖:如果
A -> B
,B -> C
,且B不决定A,则C传递依赖于A。
- 传递函数依赖:如果
- 巴斯-科德范式(BCNF):在3NF基础上,消除主属性对码的部分和传递函数依赖。可简单理解为:每个决定因素都必然包含候选码。
范式权衡:范式越高,数据冗余和异常越少,但查询时可能需要更多的表连接,性能可能下降。在实际设计中,通常会根据业务场景进行反规范化(Denormalization),即故意增加冗余以提高查询性能,这是一种“以空间换时间”的策略。
五、事务与并发控制 - 保证数据一致性
1. 事务的特性(ACID)
- 原子性(Atomicity):事务的所有操作要么全部提交,要么全部回滚。
- 一致性(Consistency):事务执行前后,数据库必须处于一致性状态。
- 隔离性(Isolation):并发执行的事务之间互不干扰。
- 持久性(Durability):事务一旦提交,其对数据的改变是永久性的。
2. 并发问题
如果不对并发事务进行控制,会导致:
- 丢失更新:两个事务同时修改同一数据,后提交的覆盖了先提交的。
- 脏读:读到了另一个未提交事务修改的数据。
- 不可重复读:同一事务内两次读取同一数据,结果不一致(因为中间被其他事务修改了)。
- 幻读:同一事务内两次执行相同的查询,返回的结果集不同(因为中间被其他事务插入了新数据)。
3. 事务隔离级别(解决并发问题的权衡)
SQL标准定义了4个级别,级别越高,一致性越强,但并发性能越低。
- 读未提交:可发生所有并发问题。
- 读已提交:解决脏读。
- 可重复读:解决脏读和不可重复读。
- 可串行化:解决所有问题,强制事务串行执行。
架构师决策:需要根据业务对一致性的要求,选择最合适的隔离级别。例如,对账系统可能需要可串行化
,而大多数Web应用使用读已提交
或可重复读
就足够了。
4. 锁机制
是实现并发控制的主要技术。
- 排他锁(X锁,写锁):事务T对数据A加X锁后,其他事务不能对A加任何锁。
- 共享锁(S锁,读锁):事务T对数据A加S锁后,其他事务只能对A加S锁,不能加X锁。
六、数据库优化 - 架构师的核心职责
1. SQL语句优化
- 避免使用
SELECT *
,只取需要的列。 - 使用
EXPLAIN
命令分析查询执行计划,查看是否使用了索引。 - 避免在
WHERE
子句中对字段进行函数操作(如WHERE YEAR(create_time) = 2023
),这会导致索引失效。 - 使用连接(JOIN)代替子查询(在大多数情况下)。
2. 索引优化
- 索引的原理:类似于书的目录,通过减少需要扫描的数据量来极大提高查询速度,但会降低增、删、改的速度(因为要维护索引)。
- 何时创建索引:
- 主键和外键通常自动创建索引。
- 在
WHERE
、ORDER BY
、GROUP BY
子句中频繁使用的列。 - 用于表连接的列。
- 索引类型:
- B+树索引:最常用的索引,适用于等值查询和范围查询。
- 哈希索引:适用于等值查询,不支持范围查询。
- 复合索引:基于多个列的索引。注意最左前缀原则。
3. 架构级优化
当单机数据库性能达到瓶颈时,架构师需要考虑:
- 读写分离:主数据库处理写操作,多个从数据库处理读操作。通过数据复制保持同步。
- 分库分表:
- 垂直分库/分表:按业务模块或将一张宽表拆分成多张小表。
- 水平分库/分表:将一张表的数据按某种规则(如时间、用户ID哈希)分布到多个数据库或表中。这是解决海量数据问题的终极方案,但会带来分布式事务、跨库查询等复杂性。
七、软考考点总结与应用
-
选择题:
- 直接考查基本概念(主键、外键、完整性约束)。
- 考查关系代数运算(给定R和S,求某个运算的结果)。
- 考查SQL语法,特别是复杂查询(带子查询、连接、分组)。
- 考查范式判断(给出表结构,判断属于第几范式)。
- 考查事务ACID特性、隔离级别和并发问题。
- 考查索引的作用和创建原则。
-
案例分析题:
- 数据库设计题:给出E-R图或需求描述,要求写出关系模式(表结构),并标明主外键。
- 问题诊断题:给出一个存在性能问题的SQL语句或数据库设计,要求分析问题(如未使用索引、存在冗余)并提出优化方案。
- 架构设计题:为高并发、海量数据的业务场景设计数据库架构方案(如是否采用读写分离、分库分表,如何分片)。
-
论文题:
- 可能围绕“论高并发数据库系统的设计与优化”、“数据库分库分表策略与实践”、“数据一致性保障技术在分布式系统中的应用”等主题。
- 写作时,可以详细论述你如何进行数据库选型、表结构设计、索引规划,以及如何通过读写分离、分库分表等技术解决性能瓶颈,并阐述在保证数据一致性方面所做的权衡和努力。
总结
对于软考架构师,掌握关系数据库的关键在于:
- 理论扎实:深刻理解关系模型、完整性约束、关系代数、范式理论。
- SQL精通:能编写高效、复杂的SQL查询,理解其执行原理。
- 设计卓越:能设计出既满足范式要求,又兼顾性能的数据库结构。
- 优化有道:具备从SQL、索引到系统架构的全链路优化能力。
- 视野开阔:理解事务、锁、隔离级别等机制在并发环境下的作用和权衡。