优化器的工作包括:
对表达式和条件的计算;
参考完整性约束,基于元数据进行优化;
语句的转换;
优化器目标的选择;
访问路径的选择;
连接顺序的选择。
优化器会对一个查询产生多个执行计划,并且计算每步的开销。具有最小开销的执行计划(execution plan)就是执行时的查询计划(query plan)。
你可以查看一个sql的执行计划,但只有真正执行时,选择的计划才是查询计划。
优化器目标:
Total throughout:ALL_ROWS
Initial response time: FIRST_ROWS
优化器流程:
1.对解析后的查询,根据可用的访问路径和hints,产生一组执行计划。
2.根据数据字典中的统计信息,对执行计划估算开销。
3.比较开销,选择最低开销的执行计划,也就是查询计划,发送到row source generator.
Query transformer:决定是否需要对查询进行转换,以得到一个更好的执行计划。
Estimator: 决定一个给定执行计划的开销。
用三个方面去度量:selectivity, cardinality, cost.
Plan generator:选择执行计划。
访问路径access path
总的来说,如果取得是表中的一小部分纪录,那么索引访问路径是最优的。如果取一大部分数据,全表扫描较好。
访问路径包括:
1.全表扫描:读取所有纪录,过滤不满足条件的。读取所有在高水位线下的数据块。
2. Rowid扫描:一行的rowid指定了数据文件,数据块,和数据块中的行位置。数据库通过where语句或者扫因扫描,得到rowid,然后定位数据。
3.索引扫描:根据索引扫描。
4.Cluster扫描;只针对索引table cluster,具有同样cluster键值的纪录放在一个数据块中。数据库先根据聚簇索引得到rowid,然后通过rowid定位纪录。
5.哈希扫描:只针对哈希聚簇,具有同样哈希值得记录放在一个数据块中。数据库先对聚簇键值作哈希运算,然后根据得到的结果扫描对应的数据块。
优化器统计信息包括:
1.表:行数目,数据块数目,行大小;
2.列:distinct value, null value,数据分布
3.索引:叶子块的数目和索引的高度。
4.系统:cpu, i/o性能和使用。
优化器hint
在优化器优化语句之前,语句需要通过语法检查,语义检查, 共享池检查。
共享池检查:
数据库用哈希算法给每个sql语句产生一个哈希值,也就是v$SQL.SQL_ID.当用户提交一个sql语句时,数据库在shared SQL area中搜索,是否已经有解析后的语句有同样的哈希值 。
如果有,则soft parse,数据库重用以有的代码,被称作library cache hit.
如果没有,则hard parse,or library cache miss。数据库多次访问library cache和数据字典,并且在访问时,用latch在锁住对象,以保证对象的定义不被改变。Latch的使用延长了语句执行时间,降低了并发性。
判断共享池中的语句是否具有相同的哈西值,不仅要看语法相同,还要看语义,比如不同用户的同名表,有可能是不同的表,甚至当语义相同时,还要看执行环境,比如优化器的设置,trace是否打开等。
Row source generator:接收来自优化器的最优执行计划,然后产生一个iterative plan。
产生一个row source tree,是一组row sources (每一步执行产生的结果集),这棵树表明了语句引用的表顺序,对每个表的访问方式,对表的连接方式,数据操作(过滤,排序,总合)等。相当于执行计划的那棵树。
Sql引擎对树的每一步执行,其中的每个节点要么从数据库取得数据,要么从其他节点取得数据。
Oracle不对DDL语句做优化。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/11903161/viewspace-676625/ ,如需转载,请注明出处,否则将追究法律责任。