# Abstract
- Query optimizer 必须知道**如何以及何时**使用物化视图。
- 本论文提供了一种快速可扩展的算法,用于决策一个查询的部分或整体是否可以借助物化视图来计算,并且描述了如何将其集成到 transformation-based optimizers。
- 仍然**保持基于成本的优化**
生成多个 rewrites,然后优化器基于成本来选择最优的。
-------------
# 1. Introduction
- 使用物化视图可以带来数量级的加速。
- 需要解决的问题:
- **View design:** 决定物化什么视图,包括如何存储和索引
- **View maintenance:** 当基础表的数据更新后如何高效更新物化视图
- **View exploitation:** 如何有效利用物化视图来加速查询处理
- 在 transformation-based optimizer 中实现
在查询的子表达式上应用 local transformion rules,将子表达式进行替换(可能为物化视图)
这一过期可能会在优化期间中调用多次(每次针对不同的子表达式)
transformation-based optimizer 基于 [[cascades-optimizer | Cascades framework ]]
- 论文主要贡献:
- 高效的**视图匹配**算法(适用于 SPJG views)
- 一种新型的**索引结构**(索引视图的定义,而非视图的数据),匹配时可以快速缩小搜索范围到一小组候选视图上
> 论文只讨论将算法应用到 SPJG viewa 和 单个视图,算法是可以扩展到更多场景的。
- 我们的视图匹配算法是快速和可扩展的:
- 复杂查询需要调用多次,因此速度很关键
- 可扩展:高效地支持几千个视图( query result cache 也可以看作是一种临时性的视图)
--------
# 2. Defining the problem
- SQL Server 2000 中的物化视图:
- 通过在已有的视图上创建**唯一的** **clustered index** 来实现物化视图,唯一意味着视图的输出必须包含一个 unique key。这是必要的,以确保视图可以增量更新
- clustered index 创建后,可以创建额外的二级索引
- 并非所有的视图都是可索引的:
> An indexable view must be defined by a single-level SQL statement containing selections, (inner) joins, and an optional group-by
- FROM 从句不能包含 derived tables(必须是 base tables,不允许子查询)
- 聚合视图的输出必须包含所有 grouping 列(它们决定了 key)
例子:
```sql
-- 创建普通 view
create view v1 with schemabinding as
select p_partkey, p_name, p_retailprice,
count_big(*) as cnt,
sum(l_extendedprice*l_quantity) as gross_revenue
from dbo.lineitem, dbo.part
where p_partkey < 1000
and p_name like ‘%steel%’
and p_partkey = l_partkey
group by p_partkey, p_name, p_retailprice
-- 物化视图,将结果存储到 clustered index
create unique clustered index v1_cidx on v1(p_partkey)
-- 在物化视图上创建二级索引
create index v1_sidx on v1( gross_revenue, p_name)
```
- **View Matching with Single-View Substitutes**
给定一个关系表达式(SPJG),找到所有可以计算该表达式的物化视图(SPJG)。
对于找到的每个视图,构建跟原表达等价的替代表达式。
不同的视图可以用来计算一个查询的不同部分。
生成的所有替换都会像正常方式一样参与 CBO。
此外,物化视图上的二级索引也会像普通 base tables 一样被考虑在内。
---------
# 3. Computing a query expression from a view
- 本章:如何判断某个表达式是否可以从一个视图中计算,以及如何构建替代表达式。
- 算法利用了四种类型的约束:
- 列上的 not-null 约束
- 主键约束
- 唯一约束
- 外键约束
- 算法假定条件:
- 视图的 selection predicates 和 查询表达式都已经被转换转 CNF。
- 执行过 join elimination,因此查询和视图的表达式不包含冗余的 tables
## 3.1 Join-select-project views and queries
- 可以通过视图计算的查询表达式,必须满足以下条件:
1. 视图包含了查询表达式需要的所有行(我们只考虑单视图替换,如果是 union 多个视图则不需要) **行限制**
2. 所有需要的行都可以从视图中查询出来(有不意味着能查,例如 selection predicate 需要的列在视图中不存在) **列限制**
3. 查询的所有输出表达式(如投影)都可以从视图中计算出来 **列限制**
4. 正确的 duplication factor。即表达式的结果如果有重复的行,则重复次数也需要是正确的。
### 3.1.1 Column equivalence classes
设表达式的过滤谓词 $W=P_1\ \wedge P_2 \ \wedge \ \cdots \wedge \ P_n$ ( CNF 形式)
可以重写为 $W = PE \wedge PNE$,其中 PE 由列相等条件组成,即形式为 $T_i.C_p \ = \ T_i.C_q$ 。
在列相等的谓词应用完后,对于 PNE 谓词 和 output columns , 一些列彼此之间是可以相互替换的(如 $C_p$ 和 $C_q$),是等价的。
可以通过 PE 条件来寻找列的等价类。
### 3.1.2 Do all required rows exist in the view
$W_q$:Query 的 where 条件
$W_v$:View 的 where 条件
Query的结果必须是 View 的子集。**这可以由 $W_q \implies Wv$** **来保证**。
需要一种算法来检测 $W_q \implies Wv$ 。
将谓词进行重写:
$W_q = P_{q,1} \wedge P_{q,2} \wedge \ \cdots \ \wedge P_{q,m}$
$W_v = P_{v,1} \wedge P_{v,2} \wedge \ \cdots \ \wedge P_{v,n}$
最简单保守的方法就是针对 $W_v$ 中的每个合取 $P_{v,i}$ ,检查是否匹配 $W_q$ 中的某个 $P_{v,i}$
如何检测两个合取是否匹配?
例如可以转换为字符串进行比较。缺点:无法匹配 $A > B$ 和 $B < A$
更复杂的:$(A/2 + B/5)\ast10 \ = \ A\ast5+B\ast2$
算法:将谓词分为三个组件,蕴含式变为:
$PE_q \wedge PR_q \wedge PU_q \implies PE_v \wedge PR_v \wedge PU_v$
- PE:所有列相等谓词
- PR:range predicates,形式 $T_i.C_p \ op \ c$,c为常量,op为
lt;$,$\leq$等
- PU:剩余的谓词
进一步将蕴含式切分为三步:
$(PE_q \wedge PR_q \wedge PU_q \implies PE_v) \\ \ \wedge \ (PE_q \wedge PR_q \wedge PU_q \implies PR_v) \ \wedge (PE_q \wedge PR_q \wedge PU_q \implies PU_v)$
再有 $(A\implies C) \implies (AB\implies C)$ ,最终将测试转换为:
- $(PE_q \implies PE_v)$ // Equijoin subsumption test
- $(PE_q \wedge PR_q) \implies PR_v$ // Range subsumption test
- $(PE_q \wedge PU_q) \implies PUv$ // Residual subsumption test
第一步执行完后,就可以应用列等价类对列进行 reroute(到其等价类)。