Oracle 优化器(Optimizer)

优化器概念

优化器具有分析SQL执行计划和路径的作用;一条SQL可能有多种执行计划,但在某一时点一定只有一种执行计划是最优的,花费时间是最少的。

优化器的优化方式

RBO方式

基于规则的优化方式(Rule-Based Optimization,简称为RBO)。优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。例如一个where子句中的一列有索引时走索引。

CBO方式

基于代价的优化方式(Cost-Based Optimization,简称为CBO)。依词义可知,它是看语句的代价(Cost)了,这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息。

统计信息给出表的大小、有少行、每行的长度等信息。这些统计信息起初在库内是没有的,是你在做analyze后才出现的,很多的时侯过期统计信息会令优化器做出一个错误的执行计划,因些我们应及时更新这些信息。可以在运行期间,采用hint灵活地采用优化方式,人工干预执行路径和方式。在Oracle8及以后的版本,Oracle列推荐用CBO的方式。

注意:不一定走索引就是优的 ,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时对这个表做全表扫描(full table scan)是最好的。

CHOOSE方式

设置缺省的Oracle优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖。为了使用基于成本的优化器(CBO, Cost-Based Optimizer) ,你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性。

如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的Oracle优化器模式将和是否运行过analyze命令有关。如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。

在缺省情况下,Oracle采用CHOOSE优化器,为了避免那些不必要的全表扫描(full table scan) ,你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的Oracle优化器。

优化器的优化模式

优化模式包括Rule,Choose,First rows,All rows四种。

Rule:不用多说,即走基于规则的方式。 (RBO优化方式)

Choose:这是我们应观注的,默认的情况下Oracle用的便是这种方式。指的是当一个表或或索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,走RBO的方式

First Rows:它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。

All Rows:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。没有统计信息则走基于规则的方式。

注意First Rows和All Rows是有冲突的.如果想最快第返回给用户,就不可能传递更多的结果,这就是First Rows返回最先检索到的行(或记录);而All Rows是为了尽量将所有的结果返回给用户,由于量大,用户就不会很快得到返回结果.就象空车能跑得很快,重装车只能慢慢地跑;

优化器的优化模式的设定

Instance级别

通过在init<实例名>.ora文件中设定
OPTIMIZER_MODE=RULE、
OPTIMIZER_MODE=CHOOSE、
OPTIMIZER_MODE=FIRST_ROWS、
OPTIMIZER_MODE=ALL_ROWS
OPTIMIZER_MODE参数默认用的是Choose这种方式。

init.ora和init<实例名>.ora都在$ORACLE_HOME/dbs目录下,可以用
find $ORACLE_HOME -name init*.ora
init.ora是对全体实例有效的;
init<实例名>.ora只对指定的实例有效.

Sessions级别

通过SQL> ALTER SESSION SET OPTIMIZER_MODE=<Mode>; 来设定,将覆盖init.ora,init<实例名>.ora设定的优化模式

语句级别

采用Hints

Q&A

问题:为什么有时一个表的某个字段明明有索引,当观察一些语的执行计划确不走索引呢?如何解决呢?
原因

  • 你在Instance级别所用的是all_rows的方式
  • 你的表的统计信息(最可能的原因)
  • 你的表很小,上文提到过的,Oracle的优化器认为不值得走索引。

解决方法

  • 可以修改init.ora中的OPTIMIZER_MODE这个参数,把它改为Rule或Choose后重启数据库
  • 更新表的统计信息
SQL>analyze table table_name delete statistics; 
  • 表小不走索引是对的,不用调的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值