优化器:oracle中优化器(Optimizer)是sql分析和执行的优化工具,它负责制订sql的执行计划。oracle的优化器有两种,基于规则的优化器(RBO)和基于代价的优化器(CBO),从oracle 10g开始,RBO已经被测底的废弃拉。
谓词:就是指一个查询中where限制条件。
基于规则的优化器(RBO):就是在优化器里面嵌入若干种规则,执行的sql语句符合哪种规则,则按照哪种规则制订出相应的执行计划。比如:表上有个索引,如果谓词上有索引列的存在,则一定会选择走索引,否则选择走全表扫描。
下面举个例子:
首先创建一个数据分布非常不均匀的表:
SQL> conn /as sysdba
已连接。
SQL> create table u1.t as select 1 id,object_name from dba_objects;
表已创建。
SQL> conn u1/u1
已连接。
SQL> update t set id = 99 where rownum = 1;
已更新 1 行。
SQL> commit;
提交完成。
SQL> create index ind_t on t(id);
索引已创建。
SQL> select id,count(*) from t group by id;
ID COUNT(*)
---------- ----------
1 50600
99 1
在这个表t中id=99的只有1条记录,剩下的全部是id=1的值。
如果发出这样的两条sql
select * from t where id = 99;
select * from t where id = 1;
在RBO 的年代里面,这两条sql的执行计划是这样的:
SQL> set autotrace traceonly
SQL> select /*+ rule */ * from t where id = 99;
执行计划
----------------------------------------------------------
Plan hash value: 4013845416
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| T |
|* 2 | INDEX RANGE SCAN | IND_T |
---------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=99)
Note
-----
- rule based optimizer used (consider using cbo) --“基于规则的优化器使用(考虑使用CBO)” 这里提示我们当前使用的优化器就是RBO
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
473 bytes sent via SQL*Net to client
400 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select /*+ rule */ * from t where id = 1;
已选择50600行。
执行计划
----------------------------------------------------------
Plan hash value: 4013845416
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| T |
|* 2 | INDEX RANGE SCAN | IND_T |
---------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=1)
Note
-----
- rule based optimizer used (consider using cbo)
统计信息
----------------------------------------------------------
1 recursive calls
0 db block gets
7044 consistent gets
98 physical reads
0 redo size
1510200 bytes sent via SQL*Net to client
37503 bytes received via SQL*Net from client
3375 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
50600 rows processed
这里set autotrace traceonly同set autotrace on一样,但是不显示查询输出。使用hint /*+ rule */的方式强制让oracle使用RBO优化器来产生执行计划。可以看见两个查询都使用了索引,但是我们知道,对于id = 1,几乎所有的数据都符合谓词条件,采用全表扫描才是最佳的选择。但是RBO做出了错误的选择。
RBO的情况就是这样,它是一种呆板、过时的优化器,已经在oracle 10g以后的版本中被测底的淘汰掉了。