1. 程式人生 > >Oracle 三種表關聯方式的總結, 使用hint來驗證

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 |
--------------------------------------------------------------------------------------