ORACLE表連接

ORACLE表連接



一、什麼是表連接?
表的連接是指在一個SQL語句中通過表與表之間的關聯,從一個或多個表檢索出相關的數據。


二、ORACLE的優化器使用的表連接有哪些?
1.嵌套循環連接(NESTED LOOP JOIN)
2.羣集連接(CLUSTER JOIN)
3.排序合併連接(SORT MERGE JOIN)
4.笛卡爾連接(CARTESIAL JOIN)
5.哈希連接(HASH JOIN)
6.索引連接(INDEX JOIN)


三、各種表連接的內部處理流程
1.嵌套循環連接(NESTED LOOP JOIN)
1)ORACLE優化器根據基於規則RBO或基於成本CBO的原則,選擇兩個表中的一個作爲驅動表,並指定其爲外部表;
2)ORACLE優化器再將另外一個表指定爲內部表;
3)ORACLE從外部表中讀取第一行,然後和內部表中的數據逐一進行對比,所有匹配的記錄放在結果集中;
4)ORACLE讀取外部表中的第二行,再和內部表中的數據逐一進行對比,所有匹配的記錄添加到結果集中;
5)重複上述步驟,直到外部表中的所有記錄全部處理完;
6)最後產生滿足要求的結果集。

2.羣集連接(CLUSTER JOIN)
羣集連接實際上是嵌套循環連接的一種特例。
1)ORACLE優化器根據基於規則RBO或基於成本CBO的原則,選擇兩個表中的一個作爲驅動表,並指定其爲外部表;
2)ORACLE優化器再將另外一個表指定爲內部表;
3)ORACLE從外部表中讀取第一行,然後在內部表中使用CLUSTER索引查找能夠匹配到的紀錄,所有匹配的記錄放在結果集中;
4)ORACLE讀取外部表中的第二行,再在內部表中使用CLUSTER索引查找能夠匹配到的紀錄,所有匹配的記錄添加到結果集中;
5)重複上述步驟,直到外部表中的所有記錄全部處理完;
6)最後產生滿足要求的結果集。
注:羣集連接的效率極高,因爲兩個參加連接的行源表實際上處於同一個物理塊上。但是,羣集連接也有其限制,沒有羣集的兩個表不可能用羣集連接。

3.排序合併連接(SORT MERGE JOIN)
1) 優化器判斷第一個行源表是否已經排序,如果已經排序,則到第3步,否則到第2步;
2) 第一個源表排序;
3) 優化器判斷第二個行源表是否已經排序,如果已經排序,則到第5步,否則到第4步;
4) 第二個源表排序;
5) 已經排過序的兩個源表進行合併操作,並生成最終的結果集。
注:在缺乏數據的選擇性或者可用的索引時,或者兩個行源表都過於龐大(所選的數據超過表記錄數的5%)時,排序合併連接將比嵌套循環連更加高效。排列合併連接需要比較大的臨時內存塊,以用於排序,

這將導致在臨時表空間佔用更多的內存和磁盤I/O。

4.笛卡爾連接(CARTESIAL JOIN)
笛卡爾連接是指在sql語句中沒有寫出表連接的條件,優化器把第一個表的每一條記錄和第二個表的所有紀錄相連接。如果第一個表的紀錄數爲m, 第二個表的紀錄數爲m,則會產生m*n條紀錄數。

5.哈希連接(HASH JOIN)
當內存能夠提供足夠的空間時,哈希(HASH)連接是ORACLE優化器通常的選擇。哈希連接中,優化器根據統計信息,首先選擇兩個表中的小表,在內存中建立這張表的基於連接鍵的哈希表;優化器再掃描表

連接中的大表,將大表中的數據與哈希表進行比較,如果有相關聯的數據,則將數據添加到結果集中。當表連接中的小表能夠完全cache到可用內存的時候,哈希連接的效果最佳。哈希連接的成本只是兩

個表從硬盤讀入到內存的成本。但是,如果哈希表過大而不能全部cache到可用內存時,優化器將會把哈希表分成多個分區,再將分區逐一cache到內存中。當表的分區超過了可用內存時,分區的部分數

據就會臨時地寫到磁盤上的臨時表空間上。因此,分區的數據寫磁盤時,比較大的區間(EXTENT)會提高I/O性能。ORACLE推薦的臨時表空間的區間是1MB。臨時表空間的區間大小由UNIFORM SIZE指定。

當哈希表構建完成後,進行下面的處理:
1)第二個大表進行掃描
2)如果大表不能完全cache到可用內存的時候,大表同樣會分成很多分區
3)大表的第一個分區cache到內存
4)對大表第一個分區的數據進行掃描,並與哈希表進行比較,如果有匹配的紀錄,添加到結果集裏面
5)與第一個分區一樣,其它的分區也類似處理。
6)所有的分區處理完後,ORACLE對產生的結果集進行歸併,彙總,產生最終的結果。
注:當哈希表過大或可用內存有限,哈希表不能完全CACHE到內存。隨着滿足連接條件的結果集的增加,可用內存會隨之下降,這時已經CACHE到內存的數據可能會重新寫回到硬盤去。如果出現這種情況

,系統的性能就會下降。當連接的兩個表是用等值連接並且表的數據量比較大時,優化器纔可能採用哈希連接。哈希連接是基於CBO的。只有在數據庫初始化參數HASH_JOIN_ENABLED設爲True,並且爲參數

PGA_AGGREGATE_TARGET設置了一個足夠大的值的時候,ORACLE纔會使用哈希邊連接。

6.索引連接(INDEX JOIN)
如果一組已存在的索引包含查詢條件所需要的信息,那麼優化器可能會選擇索引連接,通過索引查找結果集。


四、幾種常見表連接的比較
類別
嵌套循環連接 排序合併連接 哈希連接
HINT USE_NL USE_MERGE USE_HASH
條件 任何連接 不等價連接 等價連接
資源 CPU、磁盤I/O 內存、臨時表空間 內存、臨時表空間
特點 當有高選擇性索引或進行限制性搜索時效率較高,能夠快速返回第一次的搜索結果。 當缺乏索引或者索引條件模糊時,排序合併連接比嵌套循環有效 當缺乏索引或者索引條件模式時,哈希連接比嵌套循環有效。通常比排序合併連接快。
缺點 當索引丟失或者查詢條件限制不夠時,效率很低;當表的記錄數多時,效率低 所有的表都需要排序。它爲最優化的吞吐量而設計,並且在結果沒有全部找到前不返回數據。 爲建立哈希表,需要大量內存。第一次的結果返回較慢


五、連接應用舉例
SQL> create table user_info(user_id char(32),user_name varchar2(10));
SQL> create table dev_info(dev_no char(32),user_id char(32),dev_type varchar2(10));
SQL> set autotrace traceonly explain;
1.嵌套循環連接(NESTED LOOP JOIN)
SQL> select /*+ use_nl(a b) */ a.user_name, b.dev_no
from user_info a, dev_info b
where a.user_id = b.user_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1772694585

--------------------------------------------------------------------------------
| Id  | Operation       | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    48 |     4     (0)| 00:00:01 |
|   1 |  NESTED LOOPS       |           |     1 |    48 |     4     (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| USER_INFO |     1 |    24 |     2     (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| DEV_INFO  |     1 |    24 |     2     (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   3 - filter("A"."USER_ID"="B"."USER_ID")
2.排序合併連接(SORT MERGE JOIN)
SQL> select /*+ use_merge(a b) */ a.user_name, b.dev_no
from user_info a, dev_info b
where a.user_id > b.user_id;  2    3  

Execution Plan
----------------------------------------------------------
Plan hash value: 261599494

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

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

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

|   0 | SELECT STATEMENT    |        |     1 |    48 |     6  (34)| 00:00:01
|

|   1 |  MERGE JOIN        |        |     1 |    48 |     6  (34)| 00:00:01
|

|   2 |   SORT JOIN        |        |     1 |    24 |     3  (34)| 00:00:01
|

|   3 |    TABLE ACCESS FULL| USER_INFO |     1 |    24 |     2   (0)| 00:00:01
|

|*  4 |   SORT JOIN        |        |     1 |    24 |     3  (34)| 00:00:01
|

|   5 |    TABLE ACCESS FULL| DEV_INFO    |     1 |    24 |     2   (0)| 00:00:01
|

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


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

   4 - access(INTERNAL_FUNCTION("A"."USER_ID")>INTERNAL_FUNCTION("B"."USE
          R_ID"))
       filter(INTERNAL_FUNCTION("A"."USER_ID")>INTERNAL_FUNCTION("B"."USE
          R_ID"))

3.哈希連接(HASH JOIN)
SQL> select a.user_name, b.dev_no
from user_info a, dev_info b
where a.user_id = b.user_id;

Execution Plan
----------------------------------------------------------
Plan hash value: 1657342960

--------------------------------------------------------------------------------
| Id  | Operation       | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    48 |     5    (20)| 00:00:01 |
|*  1 |  HASH JOIN       |           |     1 |    48 |     5    (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| USER_INFO |     1 |    24 |     2     (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| DEV_INFO  |     1 |    24 |     2     (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - access("A"."USER_ID"="B"."USER_ID")


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章