关系数据库的查询优化

关系查询优化是影响关系数据库管理系统性能的关键因素。

一、查询优化概述

查询优化的优点不仅在于用户不必考虑如何最好地表达查询以获得较高的效率,而且在于系统可以比用户程序的“优化”做得更好。
1. 优化可以从数据字典中获得更多统计信息。
2. 如果数据库的物理统计信息改变了,系统可以自动对查询进行重新优化以选择相适应的执行计划。在非关系系统中则必须重写程序,而重写程序在实际应用中往往是不太可能的。
3. 优化器可以考虑数百种不同的执行计划,而程序员一般只能考虑有限的几种可能性。
4. 优化器中包括了很多复杂的优化技术,这些优化技术往往只有最好的程序员才能掌握。系统的自动优化相当于使得所有人都拥有这些优化技术。
在集中式数据库中,查询执行开销主要包括磁盘存取块数(I/O代价)、处理机时间(CPU代价)以及查询的内存开销。在分布式数据库中还要加上通信代价,即:
总代价=I/O代价+CPU代价+内存代价+通信代价。
由于磁盘I/O操作涉及机械动作,需要时间与内存操作相比要高几个数量级,在计算查询代价时一般用查询处理读写的块数作为衡量单位。
查询优化的总目标是选择有效的策略,求得给定关系表达式的值,使得查询代价较小,因为查询优化的搜索空间有时非常大,实际系统选择的策略不一定是最优的,而是较优的。

二、代数优化

代数优化是基于关系代数等价变换规则的优化方法。
代数优化策略是通过对关系代数表达式的等价变换来提高查询效率。所谓关系代数表达式的等价是指用相同的关系代替两个表达式中相应的关系所得到的结果是相同的。两个关系表达式E1和E2是等价的。

查询树的启发式优化

典型的启发式规则:
1. 选择运算应尽可能先做。
2. 把投影运算和选择运算同时进行。如有若干投影和选择运算,并且它们都对同一个关系操作,则可以在扫描次关系的同时完成所有这些运算以避免重复扫描关系。
3. 把投影同其前或后的双目运算结合起来,没有必要为了去掉某些字段而扫描一遍关系。
4. 把某些选择同在它前面要执行的笛卡儿积结合起来成为一个连接运算,连接(特别是等值连接)运算要啊比同样关系上的笛卡儿积省很多时间。
5. 找出公共子表达式。

三、物理优化

代数优化改变查询语句中操作的次序和组合,但不涉及底层的存取路径。物理优化就是要选择高效合理的操作算法或存取路径,求得优化的查询计划,达到查询优化的目标。
选择的方法可以是:
1. 基于规则的启发式优化。
2. 基于代价估算的优化。
3. 两者结合的优化方法。常常先使用启发式规则选取若干个较优的候选方案,减少代价估算的工作量,然后分别计算这些候选方案的执行代价,较快地选出最终的优化方法。

基于启发式规则的存取路径选择优化

选择操作的启发式规则
对于小关系,使用全表顺序扫描,即使选择列上有索引。
对于大关系,启发式规则有:
1. 对于选择条件是“主码=值”的查询,查询结果最多是一个元组,可以选择主码索引,一般都关系数据库管理系统会自动建立主码索引。
2. 对于选择条件是“非主属性=值”的查询,并且选择列上有索引,则要估算查询结果的元组数目,如果比例较小(<10%)可以使用索引扫描方法,否则还是使用全表顺序扫描。
3. 对于选择条件是属性上的非等值查询或者范围查询,并且选择列上有索引,同样要估算查询结果的元组数目,如果选择率<10%可以使用索引扫描方法,否则使用全表顺序扫描。
4. 对于用AND连接的合取选择条件,如果有涉及这些属性的组合索引,则优先采用组合索引扫描方法;如果某些属性上有一般索引,则可以使用索引扫描方法,否则使用全表顺序扫描。
5. 对于OR连接的析取选择条件,一般使用全表顺序扫描。

基于代价估算的优化

启发式规则优化是定性的选择,比较粗糙,但是实现简单而且优化本身的代价较小,适合解释执行的系统。因为解释执行的系统,其优开销包含在查询总开销之中,在编译执行的系统中,一次编译优化,多次执行,查询优化和查询执行是分开的,因此,可以用精细复杂一些的基于代价的优化方法。

四、查询计划的执行

查询优化完成后,关系数据库管理系统为用户查询生成了一个查询计划。该计划的执行可以分为自顶向下和自底向上两种执行方法。
1. 自顶向下
系统反复向查询计划顶端的操作符发出需要查询结果元组的请求,操作符收到请求后,就试图计算下一个(几个)元组并返回这些元组。在计算时,如果操作符的输入缓冲区为空,它就会向其孩子操作符发送需求元组的请求……这种需求元组的请求会一直传到叶子节点,启动叶子操作符运行,并返回其父操作符一个(几个)元组,父操作符再计算自己的输出返回给上层操作符,直至顶端操作符。重复这一过程,直到处理完整个关系。
2. 自底向上
查询计划从叶结点开始执行,叶节点操作符不断地产生元组并将它们放入其输出缓冲区中,直到缓冲区填满为止,这时它必须等待其父操作符将元组从该缓冲区中取走才能急促执行,然后其父结点操作符开始执行,利用下层的输入元组来产生它自己的输出元组,直到其输出缓冲区满为止,重复这个过程,直到产生所有的输出元组。

向下的执行方式是一种被动的、需求驱动的执行方式。而自底向上的执行方式是一种主动的执行方式。

总结:
对于比较复杂的查询,尤其是涉及连接和嵌套的查询,不要把优化的任务全部放在关系数据库管理系统上,应该找出关系数据库管理系统的优化规律,以写出适合关系数据库管理系统自动优化的SQL语句,对于关系数据库管理系统不能优化的查询需要重写查询语句,进行手工调整以优化性能。

猜你喜欢

转载自blog.csdn.net/lxw983520/article/details/81082766