Access Path Selection in a Relational Database Management System

如果说选一篇在优化器框架上,被引用次数最多的文献,应该非这篇论文莫属了,还记得Andy Pavlo在cmu的课程中提到IBM Research的一群大神们,是怎么一人一个模块来负责System R的设计的,而关于Join order enumeration,Selinger可以说是开创了dynamic programing based 的bottom-up的搜索空间算法的先河,直至今日,很多成熟的商业或开源数据库系统仍在沿用这套框架,比如Oracle / DB2 / PostgreSQL ...

最优化理论

众所周知,在广阔的plan space中寻找最优解是一个NP-hard问题,如果不采用某种特定的search路径或策略,其成本是无法接受的,而动态规划就提供了这样一个策略。

从本质上,动态规划基于成本最优假设(在最优的方案当中,取局部结构来看其方案也是最优的),将寻找全局最优解的问题分解为了对于局部最优解的迭代,不断通过子问题的局部最优,获取更大问题的局部最优,直到全局。

这里所谓的局部最优解,落到关系代数的表述方式上,就是指在当前的join子树上,获取到的已知最优结果,需要将其和计算的cost进行缓存,供子树的上层(也就是父问题)继续迭代。

看起来问题并不复杂,但对于join这样的关系代数运算来说,由于可能存在不同的执行方式(hash join/sort merge/NestLoop ...),下一层子树的输出的特性不同,对于上一层join执行的cost会产生不同的影响,比如如下子树:

Access Path Selection in a Relational Database Management System

假设由于t2表很小,在考虑第一个join时,可能有左右两图中的两种选择,而基于最优原则,在下层的小子树上,我们选择了in-memory hash join,但当迭代到上一层的join node时,由于sort merge join对于两侧的input有顺序要求,因此也许在考虑下层join时,选用sort merge join可以保留住t2.a上的有序性,从而避免了对hash join结果的排序操作而代价更低。

从以上的例子可以看到,局部最优解是有前提条件的,理论上,带有不同输出特性的子问题,被划分到不同的等价类中,属于不同的局部问题,因此应该各自维护最优解,这些局部最优解的集合都可以传递到上层以供后续迭代,这样动态规划的问题就不再是一个线性的迭代,而是自底向上,树形展开的迭代过程。

Paper

有了以上的基本概念,再去理解System-R对于join ordering的处理就相对简单了,上文所提到的每个join node的输出特性,就是描述join之后数据所具有的某种物理属性,在System-R中,这种物理属性是数据的有序性,称为Interesting Order

当然这篇paper不止是join ordering,也包含单表access path的选择,cost计算,selectivity估算等,下面一一详述。

整体框架

整体框架包含以下4个组件:

  • Parser

通过yacc解析,生成基本的Parse tree

  • Optimizer
  1. 从Catalog中读取元数据+统计信息,先做语义检查
  2. 确定各个query block的求值顺序,对每个query block,计算cost并生成最优plan, plan使用ASL语言进行描述
  3. 将ASL语言 -> machine code,对外暴露为一个函数,其中每个嵌套query block plan,都是一个子函数
  • Executor

执行machine code,过程中会调用RSI(Relational Storage Interface)接口,访问RSS存储层获取数据,RSI接口是OPEN -> NEXT -> CLOSE的方式,每次获取一个tuple。

  • RSS (Relational Storage System)
  1. 按page组织tuple数据,分为data page/index page,tuple不跨page,page逻辑上组成segment,一个segment可包含多个relation的page,relation不跨segment。
  2. 一个Page中可能包含多表的tuple。

优化流程

先给出示例用的SQL语句和schema:

Access Path Selection in a Relational Database Management System

SELECT NAME,TITLE,SAL,DNAME
FROM EMP,DEPT,JOB
WHERE TITLE=‘CLERK’
AND LOC=‘DENVER’
AND EMP.DNO=DEPT.DNO
AND EMP.JOB=JOB.JOB

整个过程是自底向上的,因此遵从单表 -> 两表 -> 三表... 的顺序,我们依次来看:

  • 单表access path选择

单表cost是两表join cost的基础,cost中包含IO + CPU两部分

Access Path Selection in a Relational Database Management System

pages fetched是IO部分,包含index page + data page的读取代价

RSICALL是进入RSS层的次数,正比于cpu的计算量,也就是 Access Path Selection in a Relational Database Management System的乘积,即返回上层的tuple数。

W 是权重比例,描述IO和cpu的成本权重。

Cost的计算要利用统计信息和选择率:

统计信息

Relation : NCARD(tuple数量),TCARD(data page数量),P(page占segment比例)

Index : NDV(index key的NDV), NINDX(index page数量) 

以上信息可以从System catalog中获取

选择率

Access Path Selection in a Relational Database Management System ,表示在scan时能够满足谓词的数据行比例,不同谓词具有不同的计算公式:

1) column = value

有索引: Access Path Selection in a Relational Database Management System  无索引 Access Path Selection in a Relational Database Management System

2) column1 = column2

两边都有索引: Access Path Selection in a Relational Database Management System

一边有索引: Access Path Selection in a Relational Database Management System

无索引 : Access Path Selection in a Relational Database Management System

3) column > value  or  column between value1 AND value2

属于range scan,对于有索引,且是数值类型的,假设均匀分布, Access Path Selection in a Relational Database Management System

4) column IN list(...)

Access Path Selection in a Relational Database Management System

假设所有value分布相同,使用list value个数 * 每个value的选择率

5) 不同谓词的逻辑组合AND/OR/NOT,基于谓词间独立性假设进行计算

Access Path Selection in a Relational Database Management System

Access Path Selection in a Relational Database Management System

Access Path Selection in a Relational Database Management System

由以上情况,可以计算出任意predicate的selectivity。

综上,可以看到Cost受到Cardinality + Selectivity的影响,由对应谓词和统计信息一起决定。最终单表的优化结果是 Cardinality + Interesting order + access cost 三个维度,结合示例中的SQL:

Access Path Selection in a Relational Database Management System

上图中,每个表右侧的一条竖线,代表一种access path,线的上方是访问方式(index scan / segment scan),下方是产生的Cardinality + Cost + Interesting Order。假设后续join对DEPT和JOB的输出Interesting Order要求是DNO和JOB,以DEPT为例,第二种access path不产生order且其cost已经比第一种要大,这里可以直接prune掉。

  • 两表join

在选择join order时有两个基本的启发规则: 

  1. 只考虑左深树的join tree形态,在System-R那个年代,内存和CPU还非常原始,采用这种策略来限制搜索空间非常明智,既可以极大的减少空间膨胀,也可以选出足够优的计划。
  2. 在选择下一个inner table时,总是选择和已选择的join tables有join条件的,尽量把笛卡尔积的计算放到最后,这也是比较符合直觉的,笛卡尔积会导致中间结果爆炸,因此拖到最后一般来说是影响最小的。(HyPer中对于join order的新DP算法中,仍然延续了这样的假设)

扩展到多表时,可以先看一下Search tree的概念,先给出2个直观的图:

Access Path Selection in a Relational Database Management System

结合Figure 2中的单表的access path选择,形成如上单表的search tree,中间节点层代表了访问的单表,而其下的一条到leaf node的边,则表示了单表的可能访问方式。比如EMP下面的两条边,分别对应Index EMP.DNO的访问方式和Index EMP.JOB的访问方式,因此在leaf node上产生的Interesting Order也有所不同。

再将两个表组合起来

Access Path Selection in a Relational Database Management System

这个图看起来很复杂,但从root节点出发只关注任一条到leaf节点的路径,就对应着一种两表join的特定组合方式,以最左侧路径为例:

(EMP,DEPT)中间节点代表了这两个表的组合,其向下延伸的第一条边是Index EMP.DNO,表示用index scan的方式访问EMP表,而再下一条边是Index DEPT.DNO,表示用index scan方式访问DEPT表,由此到达leaf node,这样就形成了两表的一种Join组合,产生了特定的(Cost + Cardinality + Interesting Order)的组合,每一条root -> leaf的边都代表这样的一种join组合。

在leaf level的各种join组合枚举完后,对每个等价类(相同table set+相同interesting order)内,选出一个最优方案,prune掉等价类内其他分支。

join cost计算和join的物理算法有关

1)NestLoop Join

Access Path Selection in a Relational Database Management System

N是所有join prefix产生的Cardinality,可以用所有prefix table的Cardinality乘积 * 所有已apply谓词(连接/过滤)选择率的乘积来计算

每个C-都是单表的access cost。

现在MySQL在做join cost的计算时,依然沿用这个公式。

2)Sort Merge Join

Access Path Selection in a Relational Database Management System

总结

System R针对join ordering问题,开创性的使用基于动态规划的方法,结合Interesting Order形成等价类的方式,来对search space进行高效搜索。不仅如此,其对于selectivity的计算,cost的计算方式,影响非常深远,相信早期的商业数据库大多采用类似的代价估算方式(MySQL直至今日仍然如此)。对后续30年间数据库的发展产生了极为深远的影响。

上一篇:2019云栖大会70+份*大咖演讲PPT分享!


下一篇:如何导入本地镜像到阿里云ECS服务器