课程目标
完成本课程的学习后,您应该能够:
优化器的类型:
基于规则的优化器(RBO,Rule-Based Optimizer)
基于成本的优化器(CBO,Cost-Based Optimizer)
1.1 RBO
基于规则的优化器诞生于早期关系型数据库,它的原理是基于一系列规则的优先顺序来分析出执行计划,以判断最优查询路径。
其中,排名越靠前,Oracle认为效率越高。例如:按索引访问的效率肯定高于全表扫描,多字段复合索引的效率高于单字段索引,等等。通俗地讲,RBO就是不关心被访问对象的实际数据分布情况、索引效率等,仅凭想象去决定应该如何去访问数据库。可见,RBO是一种非常粗放型的优化器。
RBO的优缺点:
缺点:
通过固定的规则来判断执行计划,容易制定出恶性执行计划。
不通过统计信息来判断,使得误差较大。
优点:
RBO的判断有规可循、有律可依,方便用户对优化器的选择进行正确的预测,可以按照我们所期望的方法引导优化器制定执行计划。
1.2 CBO
基于成本的优化器是关系型数据库所追求的理想型优化器,它的原理是计算了所有查询方法所需要的成本之后,从中选择一个成本最小的查询路径。
分析----CBO的数据来源
CBO在判断最优路径时,需要通过分析相关的统计信息,这些信息包括:
表中的行数
数据块数
每个数据块中的平均行数
行的平均长度
每个列常数的种类
离散程度(直方图)
列值中null的个数
聚簇因子
索引的高度
最大最小值
叶块的数量
运行系统的IO和CPU的使用情况
select * from user_tables; select * from user_indexes;
CBO的优缺点:
缺点:
优点:
a.通过统计信息对所要执行的sql进行解析,在可能存在的执行计划中进行选择,之后制定出临时的执行计划。
b.优化器通过对直方图、表的存储结构特征、索引的结构、分区类型、比较运算符等信息进行分析之后计算出各个执行计划的成本。
c.优化器对各个执行计划的成本进行比较,并从中选择一个成本最低的执行计划。
优化器的组成
a.查询转换器
b.成本估算器
c.执行计划生成器
查询转换包括:
视图合并
子查询解嵌套
谓词前推
使用物化视图进行查询重写
drop table test1 purge; drop table test2 purge; create table test1 as select * from dba_objects where rownum <=100; create table test2 as select * from dba_objects where rownum <=1000; exec dbms_stats.gather_table_stats(user,‘test1‘); exec dbms_stats.gather_table_stats(user,‘test2‘); select count(1) from test1 t1,test2 t2 where t1.object_id=t2.object_id; select count(1) from test1 t1 where t1.object_id in (select t2.object_id from test2 t2); select count(1) from test1 t1 where exists (select 1 from test2 t2 where t1.object_id = t2.object_id); --查看UNPARSED QUERY IS出即是查询转换 Alter system flush shared_pool; alter session set tracefile_identifier = ‘1111‘; alter session set events ‘10053 trace name context forever, level 1‘; select count(1) from test1 t1,test2 t2 where t1.object_id=t2.object_id; alter session set events ‘10053 trace name context off‘ ; Alter system flush shared_pool; alter session set tracefile_identifier = ‘in‘; alter session set events ‘10053 trace name context forever, level 1‘; select count(1) from test1 t1 where t1.object_id in (select t2.object_id from test2 t2); alter session set events ‘10053 trace name context off‘ ; Alter system flush shared_pool; alter session set tracefile_identifier = ‘exists‘; alter session set events ‘10053 trace name context forever, level 1‘; select count(1) from test1 t1 where exists (select 1 from test2 t2 where t1.object_id = t2.object_id); alter session set events ‘10053 trace name context off‘ ; Set autotrace traceonly select count(1) from test1 t1,test2 t2 where t1.object_id=t2.object_id; select count(1) from test1 t1 where t1.object_id in (select t2.object_id from test2 t2); select count(1) from test1 t1 where exists (select 1 from test2 t2 where t1.object_id = t2.object_id); Set autotrace off