Oracle 三种表关联方式的总结, 使用hint来验证

最近认真参加Dataguru的Oracle培训,正经学了一些东西,有时间就整理一下放到这里,以便以后学习。

今天总结一下三种表关联方式的适用场景。

1. Nested Loop

原理:从外部表中拿数据,去内部表中去比对

适用场景:

1)关联中有一个表比较小

2)被关联表的关联字段上有索引

3)索引的键值重复率不高

例子:t表为大表,d表为小表,t上有索引。

SQL> create table d as select * from dba_objects where rownum<100;

SQL> select * from t, d where t.object_id=d.object_id;


-------------------------------------------------------------------------------------
| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |      |    99 | 31482 |   102   (0)| 00:00:02 |
|   1 |  NESTED LOOPS                |      |    99 | 31482 |   102   (0)| 00:00:02 |
|   2 |   TABLE ACCESS FULL          | D    |    99 | 22275 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS BY INDEX ROWID| T    |     1 |    93 |     1   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN         | T_PK |     1 |       |     0   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

相同sql使用Hash Join的结果:

SQL> select /*+ use_hash(t d) */ * from t,d where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 68162843

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    99 | 31482 |   172   (2)| 00:00:03 |
|*  1 |  HASH JOIN         |      |    99 | 31482 |   172   (2)| 00:00:03 |
|   2 |   TABLE ACCESS FULL| D    |    99 | 22275 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T    | 53023 |  4815K|   168   (2)| 00:00:03 |
---------------------------------------------------------------------------

相同sql使用Merge Join的结果:

SQL> select /*+ use_merge(t d) */ * from t,d where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1512134595

-------------------------------------------------------------------------------------
| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |      |    99 | 31482 |  1008   (1)| 00:00:13 |
|   1 |  MERGE JOIN                  |      |    99 | 31482 |  1008   (1)| 00:00:13 |
|   2 |   TABLE ACCESS BY INDEX ROWID| T    | 53023 |  4815K|  1004   (1)| 00:00:13 |
|   3 |    INDEX FULL SCAN           | T_PK | 53023 |       |   112   (1)| 00:00:02 |
|*  4 |   SORT JOIN                  |      |    99 | 22275 |     4  (25)| 00:00:01 |
|   5 |    TABLE ACCESS FULL         | D    |    99 | 22275 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------


2.Hash Join

原理:优化器扫描小表(或数据源),利用连接键(也就是根据连接字段计算hash 值)在内存中建立hash表,然后扫描大表,每读到一条记录就来探测hash表一次,找出与hash表匹配的行。

适用场景:

1)一个大表一个小表的关联

2)表上没有索引 (关联表上没有索引,CBO不会考虑使用Nested Loop)

3)返回结果集比较大

例子:去掉t表索引

SQL> alter table t drop primary key;

Table altered.

SQL> select * from t, d where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 68162843

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    99 | 31482 |   172   (2)| 00:00:03 |
|*  1 |  HASH JOIN         |      |    99 | 31482 |   172   (2)| 00:00:03 |
|   2 |   TABLE ACCESS FULL| D    |    99 | 22275 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| T    | 53023 |  4815K|   168   (2)| 00:00:03 |
---------------------------------------------------------------------------
相同sql使用Nested Loop

SQL> select /*+ use_nl(t d) */ * from t,d where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 3796256697

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    99 | 31482 | 16448   (2)| 00:03:18 |
|   1 |  NESTED LOOPS      |      |    99 | 31482 | 16448   (2)| 00:03:18 |
|   2 |   TABLE ACCESS FULL| D    |    99 | 22275 |     3   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| T    |     1 |    93 |   166   (2)| 00:00:02 |
---------------------------------------------------------------------------

相同sql使用Merge Join

QL> select /*+ use_merge(t d) */ * from t,d where t.object_id=d.object_id;

xecution Plan
---------------------------------------------------------
lan hash value: 3365178606

-----------------------------------------------------------------------------------
 Id  | Operation           | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
   0 | SELECT STATEMENT    |      |    99 | 31482 |       |  1311   (1)| 00:00:16 |
   1 |  MERGE JOIN         |      |    99 | 31482 |       |  1311   (1)| 00:00:16 |
   2 |   SORT JOIN         |      |    99 | 22275 |       |     4  (25)| 00:00:01 |
   3 |    TABLE ACCESS FULL| D    |    99 | 22275 |       |     3   (0)| 00:00:01 |
*  4 |   SORT JOIN         |      | 53023 |  4815K|    12M|  1307   (1)| 00:00:16 |
   5 |    TABLE ACCESS FULL| T    | 53023 |  4815K|       |   168   (2)| 00:00:03 |
-----------------------------------------------------------------------------------


3.Merge Join

原理:将两个结果集分别排序,对排序后的结果集进行连接

适用场景:当结果集已经排过序

例子:先排序,再关联

SQL> select * from (select * from t order by object_id) t, (select * from d order by object_id) d
  2  where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 2926044903

-------------------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    99 | 43758 |       |  1311   (1)| 00:00:16 |
|   1 |  MERGE JOIN          |      |    99 | 43758 |       |  1311   (1)| 00:00:16 |
|   2 |   VIEW               |      | 53023 |    10M|       |  1307   (1)| 00:00:16 |
|   3 |    SORT ORDER BY     |      | 53023 |  4815K|    12M|  1307   (1)| 00:00:16 |
|   4 |     TABLE ACCESS FULL| T    | 53023 |  4815K|       |   168   (2)| 00:00:03 |
|*  5 |   SORT JOIN          |      |    99 | 22275 |       |     4  (25)| 00:00:01 |
|   6 |    TABLE ACCESS FULL | D    |    99 | 22275 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

相同sql使用Nested Loop

SQL> select /*+ use_nl(t d) */ * from (select * from t order by object_id) t, (select * from d order by object_id) d
  2  where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1008542415

--------------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |    99 | 43758 |       | 59577   (1)| 00:11:55 |
|   1 |  SORT ORDER BY        |      |    99 | 43758 |       | 59577   (1)| 00:11:55 |
|   2 |   NESTED LOOPS        |      |    99 | 43758 |       | 59576   (1)| 00:11:55 |
|   3 |    VIEW               |      | 53023 |    10M|       |  1307   (1)| 00:00:16 |
|   4 |     SORT ORDER BY     |      | 53023 |  4815K|    12M|  1307   (1)| 00:00:16 |
|   5 |      TABLE ACCESS FULL| T    | 53023 |  4815K|       |   168   (2)| 00:00:03 |
|*  6 |    TABLE ACCESS FULL  | D    |     1 |   225 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

相同sql使用Hash Join

SQL> select /*+ use_hash(t d) */ * from (select * from t order by object_id) t, (select * from d order by object_id) d
  2  where t.object_id=d.object_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 3786187078

--------------------------------------------------------------------------------------
| Id  | Operation             | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |    99 | 43758 |       |  1312   (1)| 00:00:16 |
|   1 |  SORT ORDER BY        |      |    99 | 43758 |       |  1312   (1)| 00:00:16 |
|*  2 |   HASH JOIN           |      |    99 | 43758 |       |  1311   (1)| 00:00:16 |
|   3 |    TABLE ACCESS FULL  | D    |    99 | 22275 |       |     3   (0)| 00:00:01 |
|   4 |    VIEW               |      | 53023 |    10M|       |  1307   (1)| 00:00:16 |
|   5 |     SORT ORDER BY     |      | 53023 |  4815K|    12M|  1307   (1)| 00:00:16 |
|   6 |      TABLE ACCESS FULL| T    | 53023 |  4815K|       |   168   (2)| 00:00:03 |
--------------------------------------------------------------------------------------



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值