第九章 查询的处理过程和优化
查询的详细步骤是什么?
- 语法、词法检查
- 语义检查:主要是查询中设计的关系、属性是否正确,权限是否符合,是否违背约束
- 把查询转化成查询树形式的关系代数表达式
- 对查询树(关系代数)进行代数优化和物理优化
- 根据优化后的结果生成实际要运行的查询计划,最后执行
选择的底层机制
- 简单的全表扫描:把物理外存上的表一块一块的读入内存然后从前往后依次扫描。这种方法只需要一块内存就可以运行,但是对于选择率比较低的查询,这种表的查询效率不高
- 索引扫描:若SELECT的属性上有索引,则自然可以先通过索引表找到符合条件的指针们,再通过指针直接跳转到目标表格上符合条件的元组上
PS:一般认为,选择率比较低的时候,索引更好。否则全表扫描更好。
连接的底层机制
以SELECT * FROM Student, SC WHERE Student.Sno=SC.Sno为例:
- 套循环法:把外层(Student)的数据依次带到哪层检查,如果符合WHERE的条件,则假如结果集
- 排序-合并算法:这个是基于连接字段有序的情况,对于左右两个待连接的表,左右各维护一个指针在需要连接的属性上,当左边指针的值大于右边指针的值,则移动左边指针,反之移动右边指针,当两个指针的值相同则说明找到一个符合连接条件的结果。这种算法好处是两表均只需遍历一次,坏处是需要排序
- 索引连接法:若SC表的Sno上已经建立了索引,则可以遍历Student的Sno,对每一个Sno到SC的索引表上进行查找,找到符合对应关系的就拼接起来加入结果表
- Hash Join法:这种方法的根本思想就是找一个合适的哈希函数,然后首先对元组比较少的那张表上待连接的属性进行Hash,从而得到多个桶,比如左表是元组更少的表,待连接的字段一共存在A和B两种值,于是就得到对应h_1 = Hash(A)和h_2=Hash(B)的两个桶。随后再对另一张表待连接的字段执行同样的Hash函数,如果能得到同样的h_1或h_2,则将对应桶中的元组拼接起来即可
有哪些优化方法
- 代数优化:代数关系的恒等变形,实现更加高效但是等价的查询
- 物理优化:通过对于存取路径进行选择,实现更加高效的查询。比如前面提到过,对于同样一个连接操作,在是否有索引,数据是否有序的情况下,所执行的具体连接算法可能是不同的,此时选择合适的操作就是物理优化要做的事
阐述代数优化的一般过程
- SQL语句->查询树
- 查询树->关系代数语法树
- 对关系代数语法树基于代数优化规则进行等价变形
代数优化有哪些一般性原则(启发式优化)
1.选择运算尽可能先做(最基本最重要)
2.投影和选择运算尽可能同时进行,以免多次遍历同一关系
3.把投影和前后的双目运算结合起来,能在遍历的时候顺手把投影做了就不要等到后面再遍历一遍
4.把先笛卡尔积再选择的操作合并成连接操作