ITPub博客

首页 > Linux操作系统 > Linux操作系统 > RULE模式下是否FROM列表顺序决定驱动表

RULE模式下是否FROM列表顺序决定驱动表

原创 Linux操作系统 作者:yangtingkun 时间:2010-07-12 21:48:13 0 删除 编辑

前两天在ITPUB看到这个问题,很多人有这个错误的概念,在RULE优化模式下,FROM语句中表的顺序连接的驱动表,但是事实上并不是这么简单。

 

 

其实RULE优化模式已经基本上退出了历史舞台,不过既然有人提起了,就把概念描述清楚,对RULE优化模式不感兴趣的可以无视这篇文章。

RULE方式是基于规则的,根据FROM列表中的顺序判断驱动表是规则之一,但是这个规则的优先级并不高,如果有其他优先级规则存在,则执行计划会发生改变:

SQL> CREATE TABLE T1            
  2  (ID NUMBER,
  3  NAME VARCHAR2(30));

Table created.

SQL> CREATE TABLE T2
  2  (ID NUMBER,
  3  NAME VARCHAR2(30));

Table created.

SQL> INSERT INTO T1
  2  SELECT ROWNUM, TNAME     
  3  FROM TAB;

95 rows created.

SQL> INSERT INTO T2
  2  SELECT ROWNUM, TABLE_NAME
  3  FROM DBA_TABLES;

8923 rows created.

SQL> COMMIT;

Commit complete.

下面将优化模式改为RULE模式,看看是否驱动表的选择与FROM列表中的位置有关:

SQL> ALTER SESSION SET OPTIMIZER_MODE = RULE;

Session altered.

SQL> SET AUTOT TRACE
SQL> SELECT *
  2  FROM T1, T2
  3  WHERE T1.ID = T2.ID;

95 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1792967693

------------------------------------
| Id  | Operation           | Name |
------------------------------------
|   0 | SELECT STATEMENT    |      |
|   1 |  MERGE JOIN         |      |
|   2 |   SORT JOIN         |      |
|   3 |    TABLE ACCESS FULL| T2   |
|*  4 |   SORT JOIN         |      |
|   5 |    TABLE ACCESS FULL| T1   |
------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("T1"."ID"="T2"."ID")
       filter("T1"."ID"="T2"."ID")

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         30  consistent gets
          0  physical reads
          0  redo size
       4545  bytes sent via SQL*Net to client
        558  bytes received via SQL*Net from client
          8  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
         95  rows processed

SQL> SELECT *
  2  FROM T2, T1
  3  WHERE T1.ID = T2.ID;

95 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 412793182

------------------------------------
| Id  | Operation           | Name |
------------------------------------
|   0 | SELECT STATEMENT    |      |
|   1 |  MERGE JOIN         |      |
|   2 |   SORT JOIN         |      |
|   3 |    TABLE ACCESS FULL| T1   |
|*  4 |   SORT JOIN         |      |
|   5 |    TABLE ACCESS FULL| T2   |
------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("T1"."ID"="T2"."ID")
       filter("T1"."ID"="T2"."ID")

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         30  consistent gets
          0  physical reads
          0  redo size
       4545  bytes sent via SQL*Net to client
        558  bytes received via SQL*Net from client
          8  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
         95  rows processed

可以看到,RULE优化器确实根据FROM列表中的位置来选择驱动表,FROM列表中最后一个表被作为驱动表。

但是这只是没有其他优先级更高的规则存在下的情况,只要在表中建立索引,就会导致优先级发生变化,从而导致上面的驱动表选择发生变化:

SQL> CREATE INDEX IND_T1_ID ON T1(ID);

Index created.

SQL> SELECT * 
  2  FROM T2, T1
  3  WHERE T1.ID = T2.ID;

95 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3280696534

-------------------------------------------------
| Id  | Operation                   | Name      |
-------------------------------------------------
|   0 | SELECT STATEMENT            |           |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1        |
|   2 |   NESTED LOOPS              |           |
|   3 |    TABLE ACCESS FULL        | T2        |
|*  4 |    INDEX RANGE SCAN         | IND_T1_ID |
-------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("T1"."ID"="T2"."ID")

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         54  consistent gets
          0  physical reads
          0  redo size
       4545  bytes sent via SQL*Net to client
        558  bytes received via SQL*Net from client
          8  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         95  rows processed

根据规则T1应该是驱动表,但是建立索引后,索引扫描的优先级远高于全表扫描,因此Oracle选择T2作为驱动表,将T1的执行计划变成了索引扫描。

T2上也存在索引,高优先级的规则对于驱动表的选择上条件等同,这时RULE优化器则又会根据FROM列表来判断驱动表:

SQL> CREATE INDEX IND_T2_ID ON T2(ID);

Index created.

SQL> SELECT *
  2  FROM T2, T1
  3  WHERE T1.ID = T2.ID;

95 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3621112097

-------------------------------------------------
| Id  | Operation                   | Name      |
-------------------------------------------------
|   0 | SELECT STATEMENT            |           |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2        |
|   2 |   NESTED LOOPS              |           |
|   3 |    TABLE ACCESS FULL        | T1        |
|*  4 |    INDEX RANGE SCAN         | IND_T2_ID |
-------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("T1"."ID"="T2"."ID")

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        132  consistent gets
          1  physical reads
          0  redo size
       4545  bytes sent via SQL*Net to client
        558  bytes received via SQL*Net from client
          8  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         95  rows processed

 

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-667851/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 流标记——流
请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1964
  • 访问量
    11077250