《基于Oracle的SQL优化》学习笔记 第一章 oracle里面的优化器 什么是oracle里面的优化器
1.什么是优化器
优化器(Optimizer)是Oracle内置的一个核心子系统,你可以把它理解为Oracle中的一个核心模块或者一个核心功能能组件。
2.优化器的目的
优化器的目的是按照一定判断原则来得到它认为的目标SQL在当前情况下得到最高效的执行路径(acess path),也就是说优化器的目的是为了得到目标SQL的执行计划。
3.优化器分类
依据选择执行计划时所用的判断原则,Oracle里面的优化器又分为RBO和CBO。
Oracle数据库里SQL语句的执行路径视图
4.基于规则的优化器
Oracle会在代码里给各类执行路径定一个等级,一共15个等级,从1到15。在RBO眼里,等级1的执行路径的效率最高,等级15的执行路径的小路最低。
从oracle10g开始,RBO就已经不被Oracle支持,但RBO并没有从Oracle中移除,依然可以在Oracle 11gR2中使用RBO
只要出现了以下的情形之一,Oracle不会使用RBO,而是强制使用CBO
1)目标SQL中的对象有IOT(index oraganized table)
2)目标的SQL对象有分区表
3)使用了并行查询或和并行DML
4)使用了星型连接
5)使用了哈希连接
6)使用了索引快速全扫描
7)使用了函数索引
.................
在使用RBO的情况下,一旦选择的执行计划不是当前最优的执行计划,很难对执行计划进行调整,其中一个非常关键的原因是不能使用Hint,如果在目标SQL中使用Hint就意味着启动了CBO,这里有两个例外RULE Hint和DRVING_SITE Hint
那如何对使用RBO的执行计划jin'x进行调整
其中一种可行的方法就是等价改写目标的SQL,比如在目标SQL的where条件中对number和date类型的列加sh上0(如果是char或者varchar2,可以加上一个空字符,比如 || ),这样就可以让原本走索引的走不了。
如果出现两条等级相同的目标SQL,RBO会根据相关对象在数据字典缓存中的缓存顺序和目标SQL涉及的各个对象在目标SQL文本中出现的先后顺序来综合判断。这就意味着我们可以通过调整相关对象在数据字典的缓存顺序就可以改变SQL的执行计划。
在目标SQL出现出现两条或者两条以上的执行路径的等级值相同的情况下,RBO会从右往左的顺序来决定谁是驱动表,谁是被动表,进而据此选择执行计划,如果我们改变了目标SQL中所涉及的各个对象在目标SQL文本的先后顺序,也就改变了表连接的驱动表和被动表,进而改变了执行计划。
1.1.2.基于成本的优化器
CBO会从目标SQL诸多的执行路径选择一条成本最小的执行路径最为执行计划,各条路径的成本值是根据目标SQL语句所涉及的表、索引、列等相关对象的统计信息。
CBO会认为那些消耗IO和CPU资源最好的执行路径就是当前情况下的最佳选择。
Cardinality 就是指定结果集的行数。
可选择率(Selectivity)
可选择率越大,返回结果集的cardinality值就越大,估算出来的成本值也就越大。
可传递性(Transitivity)
CBO会对原目标的SQL做简单的等价改写
CBO的局限性
CBO会默认目标SQL语句where出现的各个列是独立的,没有关联的
CBO会假设目标SQL是单独执行的,并且互相不干扰
CBO对直方图统计信息有诸多限制
CBO在解析多表连接的目标SQL,可能会漏选正确的执行计划