前段时间在网上下载了一个关于Oracle优化器的文档,原文是这样的:
如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关。 如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。
再看下一段:
“选择最有效率的表名顺序(只在基于规则的优化器中有效)    
ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理。 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。当ORACLE处理多个表时, 会运用排序及合并的方式连接它们。首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并。
随后用SCOTT用户测试了一下,现在我没有运行过analyze命令,所以按照原文说的,现在的ORACLE优化器是基于规则的(RULE),所以ORACLE会按照如上的方式来处理连接,看执行计划EXPLAIN PLAN FOR SELECT e.ENAME,d.DNAME FROM EMP e,DEPT d WHERE e.deptno=d.deptno;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 351108634
--------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Ti
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |    14 |   308 |     4   (0)| 00
|   1 |  NESTED LOOPS                |         |    14 |   308 |     4   (0)| 00
|   2 |   TABLE ACCESS FULL          | EMP     |    14 |   126 |     3   (0)| 00
|   3 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    13 |     1   (0)| 00
|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("E"."DEPTNO"="D"."DEPTNO")EXPLAIN PLAN FOR SELECT e.ENAME,d.DNAME FROM DEPT d,EMP e WHERE e.deptno=d.deptno;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 351108634
--------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Ti
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |    14 |   308 |     4   (0)| 00
|   1 |  NESTED LOOPS                |         |    14 |   308 |     4   (0)| 00
|   2 |   TABLE ACCESS FULL          | EMP     |    14 |   126 |     3   (0)| 00
|   3 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    13 |     1   (0)| 00
|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("E"."DEPTNO"="D"."DEPTNO")问题一:完全是一样的执行计划,先对EMP全表扫描,然后对DEPT索引扫描,然后做连接,没看到效果?
问题二:项目开发中,需要更改ORACLE的优化器吗?
问题三:RULE和COST两种优化器如何去选择?
谢谢

解决方案 »

  1.   

    自己顶,现在CSDN怎么发帖就给我贴广告呢,记得以前是回复量高的时候才加
      

  2.   

    “如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关。 如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。”   
    这句话换成如果执行计划cost有值,优化器模式选择为cbo,反之为rbo。analyze之后cost都会有值。“选择最有效率的表名顺序(只在基于规则的优化器中有效)”  这句话也不全对:基于规则的优化器外部表不一定都是从右向左选择的。
      

  3.   

    10g 以后对表的分析好像是自动进行的。可以通过 dba_tables 来检查一下表是否分析过。
      

  4.   

    10g默认是基于cost的,即使没有analyze,oracle分析sql时,会使用动态采样生成统计数据。
    并且根据此数据来计算cost,生成执行计划。
      

  5.   


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

  6.   


    analyze自动执行,优化器会按RULE和COST分别计算,得到最少的时间的算法来执行
    改优化器,除非有必要