形式陈述
无损要求遍历所有合法原表
固定有限属性集 、有限函数依赖公理库函数依赖与属性闭包Functional dependency · Attribute closure · Candidate key从两行的一致性定义函数依赖,用固定点计算全部可决定属性,并以有限反模型证明闭包算法完备。集 ,值来自无限共同论域。关系均为无 NULL 的有限集合。分解 满足 。使用关系代数公理库关系代数Relational algebra · Set relational algebra用选择、投影、积、重命名与集合运算组合有限关系查询,并在集合语义下解释连接和存在见证。的集合投影与自然连接,称分解相对于 无损,如果
对任何 ,包含 自动成立:原表每行的所有投影在公共列上相容,能够拼回自身。无损所要排除的是反方向中的额外元组,常称伪元组。它是模式与约束的保证,不是一份数据的偶然现象。
二元无损判据。 设 ,,则
所以只需计算 ,检查它是否包含一侧全部属性。该充要条件针对只有 FD 限制的允许实例;加入其他类别的约束后,允许实例缩小,必要条件不能未经证明地沿用。
依赖保持与两个范式
在组件 上投影依赖时,保留的是全部后承
分解保持依赖,是指 。因为每个 都来自 ,一个方向自动成立;实际要问的是全部原约束能否由局部约束联合推出。不能只查看输入列表中哪些箭头完整落在一张表上:某条局部依赖可能由跨越多个输入箭头的推导得到。
在一个组件及其投影依赖上,若每个非平凡依赖 的左侧都是该组件的超键,就满足 BCNF;非平凡指 。若对每个这样的依赖,左侧是超键或者右侧 是主属性,就满足第三范式(3NF)。主属性是属于该组件至少一个候选键的属性,不能直接照搬原模式的候选键来判断组件。
直觉
投影把一行事实切成几段,却通常不保留“这些片段原来属于同一行”的编号。重新连接时,只能依靠公共列辨认对应关系。若公共列决定一整侧,那么另一侧的每个片段只能拼上由公共列唯一确定的片段,重组就不会发明新组合。
依赖保持关心另一件事:分别检查每张子表是否合法,是否足以维护原来的全部约束。无损从一张已经合法的原表出发,先投影再重建;局部约束检查则面对分别存储或更新的子表。这两个问题的量化对象不同。更细的拆分可以消除某张表中的冗余,同时让一条跨表依赖失去方便的局部检查位置。
例子与边界
先得到无损且保持依赖的第三范式设计
沿用
先拆为 与 。公共列是 ,而 包含整个第二组件,故二元判据保证无损。两个组件投影依赖的非平凡生成基分别为 与 。这里“生成基”表示它们推出组件上的全部 FD,不是只罗列原输入中看得见的箭头:在 中,含 就能增加 ,含 就能增加 ,其他起点没有新的组件属性; 所增加的 无法再触发新规则。因此没有遗漏经原 绕行产生的局部后承。
这两个基合起来就是原 ,所以设计保持依赖。 内的候选键为 ,于是它的三个属性全是主属性,满足 3NF。不过 非平凡, 在该组件中的闭包只有 ,不是超键,所以 不满足 BCNF。 中唯一候选键是 ,所有非平凡后承都由含 的左侧给出,因此该组件满足 BCNF。这就完整验证了一套无损且保持依赖的 3NF 设计,没有诉诸一般合成算法。
继续拆到 BCNF,却失去一条依赖的局部检查
再把 按 拆成 与 。公共 决定 ,这次二分也无损。先重建 ,再与 连接,就重建原 ,因此
整体无损。三个组件投影依赖的非平凡生成基依次为 、空集、。特别是 中 不能决定 , 不能决定 ,空集也不能决定任何列,确实没有非平凡后承。 的决定属性 是键, 的 是键, 没有需检查的非平凡依赖,所以三个组件均满足 BCNF。
但在局部总集 下,,得不到 。故 没有保持。下面给出实际局部表,而不只停留在符号推导:
每个 只对应 , 中 只对应 , 没有非平凡投影依赖;所有局部检查均通过。连接却得到 、,它们共享 而具有不同 ,违反原约束。这个连接结果不满足 ,用来说明局部维护不足;它不是无损定义中“合法原表被投影后产生伪元组”的反例。
换掉一个组件,得到真正有损的分解
考虑 ,取合法原表
其中 、、。两条不同的行在 上不同,所以不违反 ;在 上因 不同而不同,所以不违反 ;在 上不同,也不违反 。同一行与自身比较当然满足三条依赖,故已核对 。
投影 保留两个 搭配同一个 ,投影 保留同一个 搭配两个 ,连接允许它们任意配对; 随后为每个 添回对应 。完整结果为:
|
|
|
|
来源 |
|
|
|
|
原行 |
|
|
|
|
伪行 |
|
|
|
|
伪行 |
|
|
|
|
原行 |
这里丢失的是 与 的原始搭配, 只能补齐 ,不能修复这种关联。因此存在满足全部原约束的关系无法重建,分解有损。某些单行表仍能成功重建,并不改变这个全实例判定。
推论与应用
二元判据的充分性
取任意合法 与任意 。存在 ,使 、。连接条件给出 。若 ,两行在整个 上相同,故 在两侧都等于 ,于是 。另一条件成立时对称地得到 。这证明连接不会多出行,再结合始终成立的原表包含方向,得到相等。
二元判据的必要性
令 。假设两个决定条件都不成立,就能在 与 各选一个属性。构造两行 :在 上都取 ,在其余属性上 取 、 取 。若某条 的左侧在两行相同,则 ,闭包性给出 ,右侧也相同。因此 满足全部 。
现在从 取 部分,从 取 部分。因为交集 ,它们相容,拼成连接中的一行 。在 的选定属性上, 与 不同;在 的选定属性上, 与 不同。所以 既不是 也不是 ,是第三个元组。由此构成合法反例,证明若无损则至少一侧必须被公共列决定。
多元设计的检查边界
二元判据只需一次闭包,其朴素成本与闭包页相同。连续无损二分提供多元无损的充分证书,本页 就是这样得到的。但任意多元分解不能通过检查若干原始组件对便直接套用同一个充要定理。函数依赖的追赶检验公理库函数依赖的追赶检验FD chase · Lossless join chase test在固定符号表中全局合并被函数依赖强制相等的值,以全标记行证明无损,以终止表构造合法有损反例。会为每个组件放一行符号,给出适用于任意有限组件数的完整判据,并在本页两套三组件设计上分别输出成功证书与合法反模型。
依赖保持也可作有限检查:枚举每个组件的属性子集 ,用原 计算 ,得到其投影依赖;再检查原 每条箭头是否由这些局部依赖推出即可。直接枚举有 个起点,因此组件规模增长时,枚举成本可能呈指数增长。实例中的小生成基让检查更透明,但它们必须先被证明覆盖全部投影后承。
参考资料