《让oracle跑得更快 》学习笔记03_RBO优化器

来源:互联网 发布:iphone7还原网络设置 编辑:程序博客网 时间:2024/05/15 00:47

第三章:优化器
作者先介绍了RBO的不足,那就是不会实事求是,不会根据变化了的环境去相应的变更策略。比如在表T中,结构如下:
Id,object_name
其中在ID中只有两个不同的值,1,99.其中值为99的记录就只有一条,因此表在ID上的分布极为不均。
SQL> select id, count(*) from t group by id;

        ID   COUNT(*)
---------- ----------
         1      47596
        99          1
对这样一个表,因为在表T(id)列上建立有索引,所以RBO只会用索引,查:
 select /*+ rule */ * from t where id = 99
SQL> /


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=HINT: RULE
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE)
   2    1     INDEX (RANGE SCAN) OF 'IND_T' (INDEX)
用索引是没错,因为ID=99的记录数就一条,但查ID=1的记录,就不需要用索引。因为表中的记录几乎全为1.用索引更慢。
  1* select /*+ rule */ * from t where id = 1
SQL> /

已选择47596行。


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=HINT: RULE
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE)
   2    1     INDEX (RANGE SCAN) OF 'IND_T' (INDEX)
因为虽然查到索引后,还要再到主表中查一次,虽然索引的数据存放有规律,但表数据却没有规律,因此此时不宜用索引。《oracle 高级专家编程》中对此有极为详细的描述。


--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL> create table t as select 1 id , object_name from dba_objects;

表已创建。

SQL> select count(*) from t;

  COUNT(*)
----------
     47597

SQL> update t set id = 99 set rownum = 1;
update t set id = 99 set rownum = 1
                     *
第 1 行出现错误:
ORA-00933: SQL 命令未正确结束


SQL> edit
已写入 file afiedt.buf

  1* update t set id = 99 where rownum = 1
SQL> /

已更新 1 行。

SQL> commit;

提交完成。

SQL> create index ind_t on t(id);

索引已创建。

SQL> select id, count(*) from t group by id;

        ID   COUNT(*)
---------- ----------
         1      47596
        99          1

SQL> select /*+ rule */ * from t where id = 99;

        ID
----------
OBJECT_NAME
--------------------------------------------------------------------------------
        99
ICOL$


SQL> set autotrace on
SQL> set autotrace traceonly
SQL> edit
已写入 file afiedt.buf

  1* select /*+ rule */ * from t where id = 99
SQL> /


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=HINT: RULE
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE)
   2    1     INDEX (RANGE SCAN) OF 'IND_T' (INDEX)

 


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        455  bytes sent via SQL*Net to client
        512  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> edit
已写入 file afiedt.buf

  1* select /*+ rule */ * from t where id = 1;
SQL> /
select /*+ rule */ * from t where id = 1;
                                        *
第 1 行出现错误:
ORA-00911: 无效字符


SQL> edit
已写入 file afiedt.buf

  1* select /*+ rule */ * from t where id = 1
SQL> /

已选择47596行。


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=HINT: RULE
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T' (TABLE)
   2    1     INDEX (RANGE SCAN) OF 'IND_T' (INDEX)

 


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       6644  consistent gets
         92  physical reads
          0  redo size
    1938133  bytes sent via SQL*Net to client
      35415  bytes received via SQL*Net from client
       3175  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      47596  rows processed