Oracle 表三種串連方式(SQL最佳化)

來源:互聯網
上載者:User

在查看SQL執行計畫時,我們會發現表的串連方式有多種,本文對錶的串連方式進行介紹以便更好看懂執行計畫和理解sql執行原理。

一、串連方式:

嵌套迴圈(Nested Loops (NL))

(散列)雜湊串連(Hash Join (HJ))

(歸併)排序合并串連(Sort Merge Join (SMJ) )

二、串連說明:

1.Oracle一次只能串連兩個表。不管查詢中有多少個表,Oracle在串連中一次僅能操作兩張表。

2.當執行多個表的串連時,最佳化器從一個表開始,將它與另一個表串連;然後將中間結果與下一個表串連,以此類推,直到處理完所有表為止。

三、表串連詳解:

1. NESTED LOOP

對於被串連的資料子集較小的情況,nested loop串連是個較好的選擇。nested loop就是掃描一個表,每讀到一條記錄,就根據索引去另一個表裡面尋找,沒有索引一般就不會是 nested loops。一般在nested loop中, 驅動表滿足條件結果集不大,被驅動表的串連欄位要有索引,這樣就走nstedloop。如果驅動表返回記錄太多,就不適合nested loops了。如果串連欄位沒有索引,則適合走hash join,因為不需要索引。

可用ordered提示來改變CBO預設的驅動表,可用USE_NL(table_name1 table_name2)提示來強制使用nested loop。

要點如下:
  1)對於被串連的資料子集較小的情況,嵌套迴圈串連是個較好的選擇
  2)使用USE_NL(table_name1 table_name2)可是強制CBO 執行嵌套迴圈串連
  3)Nested loop一般用在串連的表中有索引,並且索引選擇性較好的時候
  4)OIN的順序很重要,驅動表的記錄集一定要小,返回結果集的回應時間是最快的。
  5)Nested loops 工作方式是從一張表中讀取資料,訪問另一張表(通常是索引)來做匹配,nested loops適用的場合是當一個關聯表比較小的時候,效率會更高。

例子如下:

SQL> create table t as select * from user_tables;

表已建立。

SQL> create index index_t on t(table_name);

索引已建立。

SQL> create table t1  as  select * from user_tables where table_name like '%ACCESS%';

表已建立。

SQL> create index index_t1 on t1(table_name);

索引已建立。

SQL> begin
  2  dbms_stats.gather_table_stats(ownname =>'TEST' ,tabname =>'T');
  3  end;
  4  /

PL/SQL 過程已成功完成。

SQL> begin
  2  dbms_stats.gather_table_stats(ownname =>'TEST' ,tabname =>'T');
  3  end;
  4  /

 

由於t1表記錄很小作驅動表且t表的建有索引,適合NL,執行計畫如下:

SQL> set wrap off;
SQL> set autotrace traceonly;


SQL> select a.table_name,b.table_name from t a,t1 b
  2  where a.table_name = b.table_name;

已選擇8行。


執行計畫
----------------------------------------------------------
Plan hash value: 3579965632

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

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

|  0 | SELECT STATEMENT      |          |    8 |  280 |    4  (0)| 00:00:01

|  1 |  NESTED LOOPS        |          |    8 |  280 |    4  (0)| 00:00:01

|  2 |  INDEX FAST FULL SCAN| INDEX_T  |  1921 | 34578 |    4  (0)| 00:00:01

|*  3 |  INDEX RANGE SCAN    | INDEX_T1 |    1 |    17 |    0  (0)| 00:00:01

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


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

  3 - access("A"."TABLE_NAME"="B"."TABLE_NAME")

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


統計資訊
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        18  consistent gets
          0  physical reads
          0  redo size
        807  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          8  rows processed

SQL> select a.table_name,b.table_name from t1 a,t b
  2  where a.table_name = b.table_name;

已選擇8行。


執行計畫
----------------------------------------------------------
Plan hash value: 3579965632

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

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

|  0 | SELECT STATEMENT      |          |    8 |  280 |    4  (0)| 00:00:01

|  1 |  NESTED LOOPS        |          |    8 |  280 |    4  (0)| 00:00:01

|  2 |  INDEX FAST FULL SCAN| INDEX_T  |  1921 | 34578 |    4  (0)| 00:00:01

|*  3 |  INDEX RANGE SCAN    | INDEX_T1 |    1 |    17 |    0  (0)| 00:00:01

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


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

  3 - access("A"."TABLE_NAME"="B"."TABLE_NAME")

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


統計資訊
----------------------------------------------------------
          4  recursive calls
          0  db block gets
        23  consistent gets
          0  physical reads
          0  redo size
        807  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          8  rows processed

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

假定我們利用提示改變的表的串連順序

ORACLE的解析器按照從右至左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎資料表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎資料表。如果有3個以上的表串連查詢, 那就需要選擇交叉表(intersection table)作為基礎資料表, 交叉表是指那個被其他表所引用的表.

  • 1
  • 2
  • 3
  • 下一頁

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.