Algorithm:关系代数表达式的优化算法
Input:一个关系代数表达式的语法树
Output:计算该表达式的程序
思路:
- 选择运算应尽可能先做
- 把投影运算和选择运算同时进行:这两者都是一元操作,一个元组能不能成为结果只取决于其本身
- 把投影同其前或后的双目运算结合起来
- 把某些选择同在它前面要执行的笛卡儿积结合起来称为一个连接运算
- 找出公共子表达式
Method:
-
(S1)依据定理L4,把形如 σ F 1 ∩ F 2 ∩ … ∩ F n ( E ) ) σ_{F_1∩F_2 ∩ … ∩ F_n} (E)) σF1∩F2∩…∩Fn(E))的选择表达式变成串接形式 σ F 1 ( σ F 2 ( … ( σ F N ( E ) ) ) ) σ_{F_1}(σ_{F_2}(…(σ_{F_N} (E)))) σF1(σF2(…(σFN(E)))).
-
(S2)对每个选择,依据定理L4至L9,尽可能把它移至树的底部。
-
S3)对每个投影,依据定理L3,L7,L10和L5,尽可能把它移至树的底部。
-
(S4)依据定理L4至L5把串接的选择和投影组合为单个选择、单个投影,或者一选择后跟一个投影。
-
(S5)对修改后的语法树,将其内结点按以下方式分组: 每个二元运算结点(积、并、差、连接等)和其所有一元运算直接祖先结点放在一组;对于其后代结点,若后代结点是一串一元运算且以树叶为终点,则将这些一元运算结点放在该组中;若该二元运算结点是笛卡儿积,且其后代结点不能和它组合成等连接,则不能将后代结点归入该组。
-
(S6)产生一个程序:它以每组结点为一步,但后代组先执行。
例如:
查出1978年1月1日前被借出的所有书的书名
XLOANS是面向用户的一个视图
SELECT Title FROM XLOANS WHERE Date<=1/1/78
转换为关系代数表达式:
Π
T
I
T
L
E
(
σ
D
A
T
E
<
=
“
1
/
1
/
78
”
(
Π_{TITLE}(σ_{DATE<=“1/1/78”}(
ΠTITLE(σDATE<=“1/1/78”(XLOANS
)
)
))
))
再将视图XLOANS替换为视图的定义,得到下图右面的语法树
接下来我们就要对这颗语法树来进行优化
首先依据定理L4,把形如
σ
F
1
∩
F
2
∩
…
∩
F
n
(
E
)
)
σ_{F_1∩F_2 ∩ … ∩ F_n} (E))
σF1∩F2∩…∩Fn(E))的选择表达式变成串接形式
σ
F
1
(
σ
F
2
(
…
(
σ
F
N
(
E
)
)
)
)
σ_{F_1}(σ_{F_2}(…(σ_{F_N} (E))))
σF1(σF2(…(σFN(E)))).
对于语法树中的选择条件:
即可将语法树中的
σ
F
σ_{F}
σF拆开变成串接形式,即为
σ
F
2
∩
F
3
=
σ
F
2
(
σ
F
3
)
σ_{F_2∩F_3}=σ_{F_2}(σ_{F_3})
σF2∩F3=σF2(σF3)
然后第二步:对每个选择,依据定理L4至L9,尽可能把选择移至树的底部(尽可能地早做选择和投影)。
σ
F
1
σ_{F_1}
σF1通过交换移动到底部
σ
F
2
σ_{F_2}
σF2 通过交换移动到底部
σ
F
3
σ_{F_3}
σF3移动不了
因为
Π
S
Π_S
ΠS经过
Π
t
i
t
l
e
Π_{title}
Πtitle投影已经没有意义了,所以
Π
t
i
t
l
e
(
Π
s
)
=
Π
t
i
t
l
e
Π_{title}(Π_{s})=Π_{title}
Πtitle(Πs)=Πtitle
第三步是继续对投影运算进行移动,对每个投影,依据定理L3,L7,L10和L5,尽可能把它移至树的底部,如果一个投影是对某表达式所有属性进行的,则去掉之。
首先,
Π
t
i
t
l
e
Π_{title}
Πtitle移动不下去(因为首先
Π
t
i
t
l
e
Π_{title}
Πtitle就不包含
F
3
F_3
F3涉及的属性),就将其转换,使其包含
F
3
F_3
F3涉及的属性,然后再向下移动
然后
类似处理BORROWERS和LOANS的投影
然后对修改后的语法树,将其内结点按以下方式分组: 每个二元运算结点(积、并、差、连接等)和其所有一元运算直接祖先结点放在一组;对于其后代结点,若后代结点是一串一元运算且以树叶为终点,则将这些一元运算结点放在该组中;若该二元运算结点是笛卡儿积,且其后代结点不能和它组合成等连接,则不能将后代结点归入该组。