数据库设计
写在前面的话
本文是本学渣因为考试需要写的一篇总结,只总结了需要考察的考点,所以可能有的内容引申的不多,请见谅。
一、本节考点
- 三种层次结构对于简单树的建模方式,只考对于单一节点简单树的(多副节点的复杂树不考),邻接模型、物化路径模型以及嵌套结构模型(嵌套基本不考)在某种查询过程中的分析过程
- 上面两种模型,在建模方面两种建模的 表结构设计是什么样的
- 自顶向下和自底向上查询大概是什么样的,效率是什么样,影响效率的因素是什么:
- 如邻接模型要做一次迭代,效率影响较大,却又因为是数值比较,其速度反而是最快的
- 物化路径模型虽然比较简单,但是其需要拆分字符串并重新寻找深度等,字符串运算会导致压力比较大
二、两种层次结构模型的建模
在数据库中定义满足下面两个条件的记录以及它们之间关联的集合为层次模型:
- 有且只有一个节点无父节点,称之为根节点
- 除根节点外别的节点都有且只有一个父节点
在层次模型中,每个节点代表一个记录,记录描述了的是实体,其包含的字段描述的是实体的属性。
(例如,在部门员工表中,每个节点是一行,包含多个字段即多列)
2.1 邻接模型
用id
和parent_id
来表明层次结构
表的结构如下
(重点是前两个,后两个是属性)
特性:
- 插入、移动、删除节点快捷
- 只支持单父节点,不支持多父节点
- 删除子树较难
- 三种模型中性能最高,每秒返回的查询记录数最多
2.2 物化路径模型
使用层次式的路径明确地标识出来层次结构,路径一半保存为字符串格式, PathID(1,1.1,1.2,1.1.1,1.2.1,…)
。
每一个节点都存储了其在树中的位置信息,并且这种模式还可以体现同级节点的顺序(因为路径的标识有顺序,而邻接模型就不可以),比如家族族谱
表结构设计如下:
(重点是第一个pathid作为唯一性索引(但是不应该作为key,因为主键不要经常更新),后两个是属性,其实还可以加一个id作为索引)
特性:
- 查询编写不困难
- 计算层次不方便。
- 查询复杂度主要在路径字符串的处理
- 树的的深度要自己写函数计算,可以计算“.”的数目或者去掉“.”后字符串的长度
- 子节点有顺序,但不应该暗示任何兄弟节点的排序
- 会产生重复记录的问题
- 物化路径path不应该该是KEY,即使他们有唯一性
- 所选择的编码方式不需要完全中立
- 三种模型中性能中等
三、自顶向下与自底向上两种查询
3.1 自顶向下查询
查询某个节点的所有后代节点(比如某个团下面有哪些各级的部队)
邻接模型:
只能使用数据库提供的递归查询函数,如:
- Oracle: connect by/start with
- DB2: with+as
而Mysql没有这种函数,因此很麻烦,要像下图一样手动数深度,多次union:
物化路径模型:
只需要查找所有起始部分相同的 ID(ID 是字符串格式)
3.2 自底向上查询
查询某个节点的所有祖先节点(但是课件中的难点在于要先找到这些子节点)
邻接模型:
依旧使用数据库的递归查询函数connect by,只需要把id和pid的位置换一下,很容易实现
物化路径模型:
只需逐渐去除 ID 的尾部层次即可
四、查询效率分析
- 邻接模型的两种查询效率差不多,因为都是使用了数据库的递归查询函数,connect by函数的实现不是基于关系,而是基于过程,是提取所有相关记录再处理
- 物化路径自底向上的性能降低很多,因为自顶向下只从一个节点出发,而自底向上需要从先通过字符串处理找到多个符合的子代节点,再分别求其祖先节点
-
- 虽然邻接模型要做一次迭代,效率影响较大,却又因为是数值比较,其速度反而是最快的
- 物化路径模型虽然比较简单,但是其需要拆分字符串并重新寻找深度等,字符串运算会导致压力比较大