上一篇文章中我们描述了SPJG的物化视图的改写,其中的J只能是inner join
。本文中我们将描述outer join
的物化视图的改写。与inner join
不同,我们不能将其简单地视为笛卡尔积的问题,而是需要一些复杂的变换。
定义
这里我们对后面要用到的符号和定义做一些总结。
null−rejecting: 当一个selection条件p所引用的任意列是null,则p肯定不为true,这是我们说p是null−rejecting。
null(T): 当某一行在表T的列上全是null,则null(T)为真。比如T1⋊T2的结果中,当T1中的某行t1在T2中没有找到任何匹配的行时,我们需要对T2所对应的列填充null,那么对这一行null(T2) 就是 true。如果 T={T1,T2,…,Tn},那么null(T)=null(T1)∧null(T2)…null(Tn),null(T)=~null(T1)∧~null(T2)…∧~null(Tn)。
⊎(outer union): 假设表T1的schema是S1,表T2的schema是S2,那么T1⊎T2首先null extendT1和T2是他们的schema是S1∪S2,然后做一个union all
的操作。例如,假设T1的schema和数据如下:
T2的schema和数据如下:
那么T1⊎T2的schema和数据如下:
int | float | double | int |
---|
1 | 1.1 | null | null |
2 | 2.2 | null | null |
null | null | 3.3 | 3 |
null | null | 4.4 | 4 |
subsume: t1 subsume t2指的是t1和t2有相同的schema,t1中的null少于t2,并且t2中的某个值不是null,则t1中对应的值也不是null;而对于t2中的非null值,t1中包含相同的值。例如,t1是(1,2,null),t2是(null,2,null),则我们认为t1 subsume t2。
T↓: 如果表T中的某个tuple被另一个tuple subsume了,则去除所有这样的tuple得到的结果。
T1⊕T2(minimum union):T1⊕T2=(T1⊎T2)↓
Q1⊂sQ2(subsume contained): Q1⊂sQ2 if ∀t1∈Q1,∃t2∈Q2,t1=t2 or t2 subsumes t1
Join-Disjunctive Form
这里我们首先介绍几个变换规则:
任何一个SPOJ的表达式,如果所有的表都满足Ti=Ti↓,并且所有的selection条件都是null−rejecting的情况下,我们可以将其转化成join-disjunctive 的形式,即:
Q=δp1(Υ1)⊕δp2(Υ2)…δpn(Υn)
其中Υi=Ti1⋈Ti2…⋈Tin。这里我们将每个δpi(Υi)称作一个term,我们可以看到每个term就是一个SPJ Query。举个例子,我们可以将如下的SPOJ的Query转化成join-disjunctive form:
V=C⋊ock=ck(O×ok=lok(δlp<20L)))
转化之后的结果是:
V=δlp<20∧ok=lok∧ock=ck(C,O,L)⊕δck=ock(C,O)⊕C
从MV里计算Query
MV是否包含Query的所有行
为了从MV里计算Query的结果,我们首先要知道MV是否包含Query所需要的所有行。这里我们直接使用论文里证明过的一个定理:
假设Q1和Q2是2个SPOJ的Query,Q1′和Q2′分别是对应的join-disjunctive form。那么当且仅当∀δpi1(Υi1),∃δpj2(Υj2)∈Q2′,使得δpi1(Υi1)⊂δpj2(Υj2)时,我们有Q1⊂sQ2
从上述定理可以看出,要检测Q2是否包含Q1,只需要检查Q1′的每个term是否被包含在Q2′中。定理的证明比较复杂,这里我们不做详述。举一个例子来说明。假设
V=δcn<5∧lp<20∧ok=lok∧ock=ck(C,O,L)⊕δcn<5∧ck=ock(C,O)⊕δcn<5C
从MV中恢复Query所需要的行
假设Q1被证明包含在Q2中,那么我们要计算出Q1的值,只需要计算出Q2中对应的term的值,并且按照第一篇文章中的算法进行过滤,然后执行⊕即可得到Q1的值。
那么对于一个SPOJ的MV,如何恢复每个term的值呢?遗憾的是不是所有的term值都可以恢复的,我们这里讨论2中情况:
-
当这个term的每一行都包含一个unique key的时候,我们可以通过选出不在term上null-extend的值,然后做一个去重操作即可计算出来。假设δP(Υ)是我们需要找出的term,并且该term的每一行都以一个unqie key,则
δP(Υ)=σ(πΥ.∗δnull(Υ)V)
-
当这个term中的每一行不包含unique key的时候,如果对于该query中的其他term,存在有如下关系时,我们仍然可以计算出来。假设需要计算的term是δPi(Υi),对于该query中其他的termδPj(Υj),我们都满足2中条件之一:
a. {Ti1,Ti2,…,Tin}⊂{Tj1,Tj2,…,Tjn} and{Tj1,Tj2,…,Tjn}⊂{Ti1,Ti2,…,Tin}
b. {Ti1,Ti2,…,Tin}⊂{Tj1,Tj2,…,Tjn},但是{Ti1,Ti2,…,Tin} 是被通过一些列的cardinality reserving的join跟剩余的table join起来。
当满足上述条件之后,我们发现δPi(Υi)在MV中的duplication factor是正确的,如此我们通过如下的操作即可恢复出δPi(Υi)的值:
δPi(Υi)=πΥi.∗δnull(Υi)V
当我们需要计算多个term的时候,需要注意避免多次扫描MV,而是通过把⊕转换成union来做。
SPOJG的改写
SPOJG的改写与上一篇文章中提到的SPJG的改写基本相同,但是在恢复tuple的时候我们要注意SPOJ的特殊部分,因此每个tuple的duplication factor应该相同,这里就不在赘述。
参考文献
- View Matching for Outer-Join Views, 2005
- Outerjoins as disjunctions, 1994