本章讲解查询编译器及其优化器的体系结构。查询处理器有三大步骤:
- 语法分析,将SQL转换成语法分析树
- 生成逻辑执行计划,将语法分析树转换成关系代数表达式
- 生成物理执行计划,物理查询计划,指明了要执行的操作,而且找出了这些操作执行的顺序,执行每步所用的算法,获得所存储数据的方式,以及数据从一个操作传递到另一个操作的方式。
5.1 语法分析和预处理
5.1.1 语法分析与语法分析树
语法分析树的节点有两种:
- 原子。如关键字,关系或属性的名称,常数,括号,运算符,以及其他模式成分。
- 语法类。在一个查询中起相似作用的查询子成分所形成族的名称。如<Query>表示 select-from-where 形式的查询,<Condition>表示属于条件的任何表达式。
一般,原子是叶子节点;语法类,其子节点通过该语言的语法规则之一进行描述。
如何设计一个语言的语法以及如何进行语法分析,即将一个程序或查询语言转换成语法分析树,这些属于编译领域。
5.1.2 SQL一个简单子集的语法
数据表模式如下
StarsIn(movieTitle, movieYear, starName)
MovieStar(name, address, gender, birthdate)
SELECT movieTitle
FROM StarsIn
WHERE starName IN (
SELECT name
FROM MovieStart
WHERE birthdate LIKE '%1960'
SELECT movieTitle
FROM StarsIn, MovieStar
WHERE starName = name AND birthdate LIKE '%1960'
5.1.3 预处理器
预处理器有多个重要的功能。
- 视图查询替换
- 语义检查。如检查表是否存在;检查字段是否在表中;也会检查字段是否有二义性等
- 检查类型。如属性的类型必须与其使用相适应。
5.1.4 预处理涉及视图的查询
视图实际上就是一个查询语句。如果一条SQL查询中用到了一个视图,则在from列表中用到该视图的地方,必须用模式该视图的语法树来替换。
下面举一个例子,创建视图
CREATE VIEW ParamountMovies AS
SELECT title, year
FROM Movies
WHERE studioName='Paramount'
SELECT title
FROM ParamountMovies
WHERE year=1979
其关系代数表达式树如下
下面左图就是视图预处理的正式结果,对视图进行了替换。但是,还可以使用查询处理技术对左图所示的树进行改进,如将选择和投影操作向树的底层移动和合并。
5.2 用于改进查询计划的代数定律
本节列出一些代数定律,用于将一个表达式树转换成一个等价的表达式树,后者可能有更有效的物理查询计划。
5.2.1 交换律与结合律
与数学定义保持一致。
交换律:该运算符的参数的顺序无关紧要,可以交换。
结合律:该运算符出现的两个地方,既可以从左边进行组合,也可以从右边进行组合。
当一个运算符既满足结合律,又满足交换律,则可以对用这个运算符连接起来的任意多个操作数进行随意组合与排列,而不会改变结果。例如,((w+x)+y)+z=(y+x)+(w+z)。
5.2.2 涉及选择的定律
由于选择可以明显地减少关系的大小,因此,进行有序查询处理最重要的规则之一就是只要不改变表达式的结果,就把选择在语法树上尽可能地下移。
当选择条件比较复杂时,将条件分解,这样好处是,部分条件涉及的属性较少,可移到某个方便的地方,而整体条件不一定能够移入。这就是分解定律。我们也可以任意交换选择运算符的顺序。
对于二元运算符进行下推选择,如积,并,交,差,连接。取决于下推选择到每个参数是可选还是必须的。
- 对于并,选择必须下推到两个参数中
- 对于差,选择必须下推到第一个参数中,第二个参数可选
- 对于其他运算符,只要求选择下推到其中一个参数。对于连接和积,将选择下推到两个参数是没有意义的,因为参数可能没有选择所要求的属性。另外,即使可以同时下推到两者,该做法也不一定能改进计划。
5.2.3 下推选择
不一定非要进行下推操作,有时候也要上移。例如当查询包含视图时,有时首先将选择尽可能的往树的上部移动,然后再把选择下推到所有可能的分支。
5.2.4 涉及投影的定律
下推投影时,投影一般留在原处,即下推投影确实涉及在一个已存在的投影之下的某个地方引入一个新的投影。
下推投影是有用的,但不如下推选择那么有用。原因是,选择通常以较大的因子减少关系的大小,而投影不改变元组,只减少元组的长度。
5.2.6 有关去重的定律
一般而言,将去重操作移到树的下边,减少了中间关系的大小,从而可能是有用的。