浅析驱动表和leading

首先大致讲一下个人对驱动表的理解:

驱动表(driving table/outer table)又称外层表,驱动表用于nested_loop join hash join,驱动表是用来驱动查询的,再CBO中,优化器会根据cost自动选择驱动表,并非根据表的顺序。

RBO的优化模式下,对于两个表的操作中,RBO选择最右的表作为驱动表,对于三个或三个以上的表,RBO选择以从右至左的顺序处理表连接,也就是from中最右端的表作为驱动表。对于NESTED LOOPSHASH JOINSORT MERGE JOIN方式,驱动表以小表的话查询速度会更快(更为确切的说,以经过where条件过滤后的结果集小的表作为驱动表),如果涉及到多个表进行关联的话,驱动表应该选择关联次数最多的表。

 

创建测试用户。

SQL> create user hint_test identified by hint_test;

User created.

SQL> grant dba to hint_test;

Grant succeeded.

SQL> conn hint_test/hint_test;

Connected.

 

创建测试表

SQL> create table t1 as select * from user_tables;

Table created.

SQL> create table t2 as select * from user_indexes;

Table created.

 

查看相对应的执行计划

SQL> select count(*) from t1,t2 where t1.table_name=t2.table_name;

Execution Plan

----------------------------------------------------------

Plan hash value: 906334482

----------------------------------------------------------------------------

| Id  | Operation     | Name | Rows  | Bytes | Cost (%CPU)| Time    |

----------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |    |  1 | 34 | 24   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE     |    |  1 | 34 | |    |

|*  2 |   HASH JOIN     |    |  1251 | 42534 | 24   (0)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| T1   |  1014 | 17238 | 11   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| T2   |  1251 | 21267 | 13   (0)| 00:00:01 |

----------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("T1"."TABLE_NAME"="T2"."TABLE_NAME")

Note

-----

   - dynamic sampling used for this statement (level=2)

Statistics

----------------------------------------------------------

157  recursive calls

  0  db block gets

230  consistent gets

 76  physical reads

  0  redo size

527  bytes sent via SQL*Net to client

524  bytes received via SQL*Net from client

  2  SQL*Net roundtrips to/from client

 12  sorts (memory)

  0  sorts (disk)

  1  rows processed

 

SQL> select count(*) from t2,t1 where t1.table_name=t2.table_name;

Execution Plan

----------------------------------------------------------

Plan hash value: 906334482

----------------------------------------------------------------------------

| Id  | Operation     | Name | Rows  | Bytes | Cost (%CPU)| Time    |

----------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |    |  1 | 34 | 24   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE     |    |  1 | 34 | |    |

|*  2 |   HASH JOIN     |    |  1251 | 42534 | 24   (0)| 00:00:01 |

|   3 |    TABLE ACCESS FULL| T1   |  1014 | 17238 | 11   (0)| 00:00:01 |

|   4 |    TABLE ACCESS FULL| T2   |  1251 | 21267 | 13   (0)| 00:00:01 |

----------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("T1"."TABLE_NAME"="T2"."TABLE_NAME")

Note

-----

   - dynamic sampling used for this statement (level=2)

Statistics

----------------------------------------------------------

  7  recursive calls

  0  db block gets

166  consistent gets

  0  physical reads

  0  redo size

527  bytes sent via SQL*Net to client

524  bytes received via SQL*Net from client

  2  SQL*Net roundtrips to/from client

  2  sorts (memory)

  0  sorts (disk)

  1  rows processed

 

这时候我们发现oracle对这两条语句产生的执行计划是一样的,我们再查看下相对应的优化器是什么模式。

SQL> show parameter optimizer_mode;         

NAME      TYPE  VALUE

------------------------------------ ----------- ------------------------------

optimizer_mode      string  ALL_ROWS

 

优化器的模式包括RuleChooseFirst rowsAll rows这四种模式,大致介绍下这四种模式:

 

Rule:基于规则的优化器(RBO优化方式)

Choose:指的是当一个表存在索引或者统计信息,则会走CBO的方式,如果一个表有索引,但是没有统计信息,表又不是很小,而且相对应的列有索引,那么就走索引,走的是RBO的方式。

First Rows:这种优化器的模式与Choose的优化差不多,但是有所不同的地方在于当我一个表存在统计信息的时候,他将以最快的速度返回查询的前几行,从总体上来说,减少了响应时间。

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

 

所以这时候我们修改下优化器模式,再查看下执行计划。

SQL> alter system set optimizer_mode = 'Rule' scope=both;

System altered.

SQL> show parameter optimizer_mode;

NAME      TYPE  VALUE

------------------------------------ ----------- ------------------------------

optimizer_mode      string  RULE

 

SQL>  select count(*) from t1,t2 where t1.table_name=t2.table_name;

Execution Plan

----------------------------------------------------------

Plan hash value: 1400713901

-------------------------------------

| Id  | Operation      | Name |

-------------------------------------

|   0 | SELECT STATEMENT     |     |

|   1 |  SORT AGGREGATE      |     |

|   2 |   MERGE JOIN      |     |

|   3 |    SORT JOIN      |     |

|   4 |     TABLE ACCESS FULL| T2   |

|*  5 |    SORT JOIN      |     |

|   6 |     TABLE ACCESS FULL| T1   |

-------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   5 - access("T1"."TABLE_NAME"="T2"."TABLE_NAME")

       filter("T1"."TABLE_NAME"="T2"."TABLE_NAME")

Note

-----

   - rule based optimizer used (consider using cbo)

Statistics

----------------------------------------------------------

  1  recursive calls

  0  db block gets

  0  consistent gets

  0  physical reads

  0  redo size

525  bytes sent via SQL*Net to client

524  bytes received via SQL*Net from client

  2  SQL*Net roundtrips to/from client

  1  sorts (memory)

  0  sorts (disk)

  1  rows processed

 

以上T2是驱动表

 

SQL> select count(*) from t2,t1 where t1.table_name=t2.table_name;

Execution Plan

----------------------------------------------------------

Plan hash value: 2721375620

-------------------------------------

| Id  | Operation      | Name |

-------------------------------------

|   0 | SELECT STATEMENT     |     |

|   1 |  SORT AGGREGATE      |     |

|   2 |   MERGE JOIN      |     |

|   3 |    SORT JOIN      |     |

|   4 |     TABLE ACCESS FULL| T1   |

|*  5 |    SORT JOIN      |     |

|   6 |     TABLE ACCESS FULL| T2   |

-------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   5 - access("T1"."TABLE_NAME"="T2"."TABLE_NAME")

       filter("T1"."TABLE_NAME"="T2"."TABLE_NAME")

Note

-----

   - rule based optimizer used (consider using cbo)

Statistics

----------------------------------------------------------

  1  recursive calls

  0  db block gets

  0  consistent gets

  0  physical reads

  0  redo size

525  bytes sent via SQL*Net to client

524  bytes received via SQL*Net from client

  2  SQL*Net roundtrips to/from client

  1  sorts (memory)

  0  sorts (disk)

  1  rows processed

 

以上T1是驱动表

 

 

/*+

ordered

use_hash(t2)

use_hash(t3)

swap_join_inputs(t3)

use_hash(t4)

no_swap_join_inputs(t4)

*/

oracle中改变表连接的hintorderedleadingordered表示根据from后面写的表的顺序作为连接,以上面的hint为例分开写思路会清晰些。orderedfrom t1,t2,t3,t4说明首先使用t1作为驱动表,使用hint use_hash(t2)代表连接t2的方式是hash join;然后用use_hash(t3)表示t3的方式是hash join,以swap_join_inputs(t3)代表t3build表和t1-t2结果集做连接,依次类推。leading可以用来替换ordered,后面无需跟from,直接leading(t1,t2,t3,t4),也可以leading(t1)表示以t1作为驱动表

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

转载于:http://blog.itpub.net/30604784/viewspace-2132539/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值