查询优化是查询处理中的重要一环,对关系DB尤其如此。
对查询进行等效变换,降低中间结果的大小。
先做选择、投影(消去大量记录和属性);先做小关系间的连接,再做大关系的连接。还可以找出查询中的公共表达式,避免重复运算。
将SQL语句转化为查询树
尽量下压选择操作(向下派发WHERE条件)
优先连接小的关系
用投影消除无用属性
例子:
SELECT SNAME FROM S,P,SP WHERE S.SNUM=SP.SNUM AND SP.PNUM=P.PNUM AND S.CITY=‘NANJING‘ AND P.PNAME=‘BOLT‘ AND SP.QUAN>10000 --- 查询在南京的商店螺栓库存大于10000的商店名
对于嵌套查询,优化比较复杂。
之前讨论的是对查询语句进行等效变换实现优化,这里讨论与物理存取路径相关的优化。
顺序扫描是最基础的,尽量利用索引、散列。
连接操作的开销很大,是优化的重点。
嵌套循环法:通过双重循环进行连接
假设R和S进行连接,双重循环中,R只要扫描一次,S要扫描多次,称R为外关系(外循环的关系),S为内关系(内循环的关系)。则有如下结论:
利用索引或散列寻找匹配元组
嵌套循环法内关系上要做多次顺序扫描,若内关系上有合适的存取路径,可以避免顺序扫描。
但注意:
排序归并
如果R和S已经按连接属性排序,可以按序比较R.A和S.B来找出匹配元组(类似于归并排序的归并过程)
散列连接
连接属性有相同的值域,选择一个相同的散列函数,把R和S按R.A和S.B散列到同一散列文件中,则可能符合连接条件的元组必然落到同一桶中,对桶中的元素进行判定(因为散列可能冲突)并连接即可。
为了减少IO次数,可以使用元组的tid代替元组本身,以缩小散列大小,争取一次扫描完成。
上述几种方法各有优缺点,选用时可参考如下的启发式规则:
一般与选择、连接同时进行,无需附加的I/O开销。
如果需要消除重复元组,可以用排序或散列等方法。
有时,多个操作组合起来同时进行,如投影和选择操作组合起来执行,可提高效益。
执行前进行优化称为静态优化,只能利用统计数据,不一定准。
执行时进行优化称为动态优化,用实际执行结果估算代价,比较符合实际;但每次执行都要优化,不适于编译实现,也增加了执行时间;只能利用统计数据,有时不一定准;要等待中间结果,增加了等待时间和数据的相关性,不利于并行性。
原文:https://www.cnblogs.com/zxuuu/p/12981185.html