幸运的是,SQL 标准中定义的聚合函数 F(col)F(col) 都是 OK 的——它们都满足 F(∅)=F({NULL})F(∅)=F({NULL}),我们只要对 FF 稍加变换就能解决这个问题 。
- 对于例子一,将 COUNT(*) 替换成一个对非空列(例如主键)的 Count 即可,例如:COUNT(o_orderkey);
- 对于例子二,需要把 MIN(IF_NULL(o_totalprice, 42)) 分成两步来做:定义中间变量 X,先用 Project 计算 X = IF_NULL(o_totalprice, 42),再对聚合函数 MIN(X) 进行去关联化即可 。
下面的等式中,×× 表示 Cross Join,?R.key?R.key 表示按照 RR 的 Key 做自然连接:r°e1°e2r°e1°e2。和之前一样,我们假设 RR 存在主键或唯一键,如果没有也可以在 Scan 的时候加上一个 。
文章插图
文章插图
注意到,这些规则与之前我们见过的规则有个显著的不同:等式右边 RR 出现了两次 。这样一来,要么我们把这颗子树拷贝一份,要么做成一个 DAG 的执行计划,总之会麻烦许多 。
事实上,这一组规则很少能派上用场 。在 [2] 中提到,在 TPC-H 的 Schema 下甚至很难写出一个带有 Union All 的、有意义的子查询 。
其他有几个我认为比较重要的点,用 FAQ 的形式列在下面 。
? 是否任意的关联子查询都可以被去关联化?
【SQL 子查询优化详解】可以说是这样的,在加上少量限定之后,理论上可以证明:任意的关联子查询都可以被去关联化 。
证明方法在 [1]、[3] 中都有提及 。以 [1] 中为例,思路大致是:
- 对于任意的查询关系树,首先将关联子查询从表达式中提取出来,用 Apply 算子表示;
- 一步步去掉其中非基本关系算子,首先,通过等价变换去掉 Union 和 Subtract;
- 进一步缩小算子集合,去掉 OuterJoin、ALOJALOJ、A∃A∃、A?A?;
- 最后,去掉所有的 A×A×,剩下的关系树仅包含基本的一些关系算子,即完成了去关联化 。
? HyPer 和 SQL Server 的做法有什么异同?
HyPer 的理论覆盖了更多的去关联化场景 。例如各种 Join 等算子,[3] 中都给出了相应的等价变换规则(作为例子,下图是对 Outer Join 的变换) 。而在 [1] 中仅仅是证明了这些情况都可以被规约到可处理的情形(实际上嘛,可想而知,一定是没有处理的) 。
文章插图
另一个细节是,HyPer 中还存在这样一条规则:
文章插图
其中,D=ΠF(T2)∩A(T1)(T1)D=ΠF(T2)∩A(T1)(T1),表示对 T1T1 的 Distinct Project 结果(所谓的
推荐阅读
- 曹操的谋士叫荀什么,荀彧的侄子荀攸
- CentOS 如何用rpm安装Mysql
- 元顺帝和朱元璋,朱棣是朱元璋的亲生儿子吗
- 仪嫔的孩子是谁害死的
- 卫子夫最后结局,卫子夫怎么死的呢
- 玉蝴蝶茶的功效与禁忌,玉蝴蝶茶的功效和功能
- 吃莲子有湿气的人可以吃吗,有湿气的人
- 宝宝多大合适给婆婆带
- 宝宝讲话迟怎么办
- 婴儿有时候一抖一抖的