在单机数据库系统中进行优化。面临的问题,好比说给定一个要query的sql语句,查询优化算法的目标就是找到查询的一个具备最小执行花费的执行计划,若是找到了,那么这样的执行计划必定具备最快的响应时间。
查询语句可表示成一颗二叉树,其中叶子表明关系,内部结点是运算符,表示左右子树的链接关系,子树是sql片断或子表达式。根节点是最后运算的操做符。根节点运算以后,获得的是sql查询优化后的结果。这样一棵树就是查询路径。多个关系链接,链接顺序不一样,能够得出多个相似的二叉树。
查询优化就是找出代价最小的二叉树,即最优的查询路径。
每条路径的生成,包括单表扫描,两表链接,多表链接顺序,多表链接搜索空间等技术。算法
思路一:逻辑优化,找出SQL语句等价的变换形式,使得sql执行更高效。优化操做依赖于表的一些属性信息(如索引和约束等)
- 子句局部优化:等价谓词重写,where和having条件化简
一、等价谓词重写
列举常见的等价谓词重写(like规则,between-and规则,in转换成or规则,NOT规则,or重写Union规则,这些规则的前提是要查询的字段创建索引;or转换any规则就是or谓词的any等价重写,以更好的利用min/max操做进行优化;all/any转换min/max规则,>any等价于min,<all等价于max;)?
答:like谓词是sql标准支持的一种模式匹配比较操做,like规则是对like谓词的等价重写。如name like 'Abc%'
能够改写成name>='Abc' and name < 'Abd'
;
between-and谓词是sql标准支持的一种范围比较操做,between-and规则是指between-and谓词的等价重写。如sno between 10 and 20
要重写为sno>10 and sno <= 20
;
此处的in是in操做符,不是in查询。in转换成or规则是将In谓词转换成等价的or谓词,以更好的利用索引优化,如age in(8,12,21)
重写为age=8 or age=12 or age=21
;
NOT规则,如not(col_1 != 2)
重写为col_1=2
;
or重写union规则,如SELECT * FROM student WHERE(sex='f' AND sno>15) OR age>18
;改写成SELECT * FROM student WHERE sex='f' and sno>15 UNION SELECT * FROM student WHERE age>18
;
all/any转换min/max规则,如sno>any(10,2*5+3,sqrt(9))
找其中的最小值 重写为sno>min(10,2*5+3,sqrt(9))
;
应用like规则和between-and规则,in转换成or规则,not规则的好处是?
答:转换前对于like谓词只能进行全表扫描,若是name列上存在索引,则转换后能够进行索引范围扫描。转换前对于between-and谓词限定的全表扫描,若是在sno上创建索引,能够用索引范围扫描。in转换or规则后效率可否提升,须要看数据库对in谓词是否只支持全表扫描。若是数据库对In谓词只支持全表扫描且or谓词字段存在索引,则使用转换规则后效率会提升;not规则,若是在字段创建了索引,就能够用索引扫描代替原来的全表扫描。
二、where,having和on条件化简
将having条件并入where条件,只有在sql语句中不存在group by条件或汇集函数的状况下,才能having条件与where条件进行合并。去除冗余括号,常量传递,消除死码,表达式计算,等式变换,不等式变换,布尔表达式变换,利用索引。这几项过于简单,不作展开描述
- 子句间关联优化(子句与子句之间关联的语义):外链接消除,嵌套链接消除,子查询优化,视图重写等都属于子句间的关联优化,由于它们的优化都须要借助其余子句,表定义或列属性等信息
一、外链接消除
外链接是什么?
答:左外链接,右外链接,全外链接。链接过程当中,外链接的左右子树不能互换。它的这种性质限制了优化器在选择链接顺序时可以考虑的表与表交换链接位置的优化方式。
优化时将外链接转换成内链接的意义
答:查询优化器在处理外链接操做时所须要执行的操做和时间多于内链接。优化器在选择表的链接顺序时,能够有更多更灵活的选择,从而能够选择更好的表链接顺序,加快查询执行的速度。表的一些链接算法(如块嵌套链接和索引循环链接等)将规模小的或筛选条件最严格的表做为“外表”(放在链接顺序的最前面,是多层循环体的外循环层),能够减小没必要要的IO开销,极大地加快算法执行速度。
外链接消除的条件
答:where子句中与内表相关的条件知足“空值拒绝”
二、嵌套链接消除
嵌套链接及嵌套链接消除是什么?
答:当执行链接操做的次序不是从左到右逐个进行时,就说明这样的链接表达式存在嵌套。如select * from t1 left join(t2 left join t3 on t2.b = t3.b) on t1.a = t2.a where t1.a > 1;
先t2与t3链接,获得中间结果{t2t3}后再与t1链接,去掉括号会影响语义。还有形如select * from a join (b join c on b.b1 = c.c1) on a.a1 = b.b1 where a.a1 > 1;
去掉括号对语义没有影响,因此能够消除。还有链接表达式只包括内链接,就能够去掉括号。由于内链接表之间的次序能够互换。若是是外链接,至多转化成内链接,再消除。
三、子查询优化
为啥要执行子查询优化?
答:查询优化器对子查询通常采用嵌套执行方式,即对父查询中的每一行,都执行一次子查询,这样子查询会执行不少次。因此会让查询效率下降。所以对于子查询的优化,可能带来几个数量级的查询效率的提升。把子查询变成链接操做以后,子查询不用执行不少次。优化器能够根据统计信息来选择不一样的链接方法和不一样的链接顺序。子查询中的链接条件,过滤条件分别变成了父查询的链接条件,过滤条件,优化器能够对这些条件进行下推,以提升执行效率。
何时子查询只能单独求解?
答:若是子查询出现汇集,group by,distinct,子查询只能单独求解,不能够拉到上层。
最多见的子查询类型优化?
答:常见子查询格式有in类型,all/any/some类型,exists类型。
四、视图重写
创建视图。
- 语义优化:根据完整性约束,sql表达含义等信息对语句进行语义优化
语义优化有哪些
groupby 优化
一、分组操做下移 :groupby 操做可能较大幅度地减小关系元组的个数,若是能对某个关系先进行分组操做,再进行表的链接,会提升链接效率。这种优化方式是把分组操做提早执行。下移含义,是在查询树上让分组操做尽可能靠近叶子节点,使得分组操做的结点低于一些选择操做。
二、分组操做上移 :若是链接操做可以过滤掉大部分元组,则先进行链接后进行groupby操做,可能提升分组操做效率。这种优化方式是把分组操做置后执行。
order by优化
排序消除,优化器在生成执行计划以前,将语句中没有必要的排序操做消除(利用索引),避免在执行计划中出现排序操做或由排序致使的操做。
排序下推,把排序操做尽可能下推到基表中,有序的基表进行链接后的结果符合排序的语义,这样能避免在最终的大的链接结果集上执行排序操做。
distinct优化
distinct消除:若是表中存在主键,惟一约束,索引等,则能够消除查询语句中的distinct。
distinct推入:生成含distinct的反半链接查询执行计划时,先进行反半链接再进行distinct操做,也许先执行distinct操做再执行反半链接更优,这是利用链接语义上确保惟一功能特性进行distinct的优化。
distinct迁移:对链接操做的结果执行distinct,可能把distinct移到一个子查询中优先进行。
- 其余优化:根据一些规则对非SPJ作的其余优化,根据硬件环境进行的并行查询优化