三種連結方式的區別
1 nested loops join
--我們用設定statistics_level=all的方式來觀察如下表連線語句的執行計劃:
--T2表被訪問100次(驅動表訪問1次,被驅動表訪問100次)
--這個set linesize 1000對dbms_xplan.display_cursor還是有影響的,如果沒有設定,預設情況下的輸出,將會少了很多列,如BUFFERS等
Set linesize 1000
alter session set statistics_level=all ;
SELECT /*+ leading(t1) use_nl(t2)*/ *
FROM t1, t2
WHERE t1.id = t2.t1_id;
--略去記錄結果
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 100 |00:00:00.94 | 100K|
| 1 | NESTED LOOPS | | 1 | 100 | 100 |00:00:00.94 | 100K|
| 2 | TABLE ACCESS FULL| T1 | 1 | 100 | 100 |00:00:00.01 | 14 |
|* 3 | TABLE ACCESS FULL| T2 | 100 | 1 | 100 |00:00:00.94 | 100K|
-------------------------------------------------------------------------------------
3 - filter("T1"."ID"="T2"."T1_ID")
---換個語句,這次T2表被訪問2次(驅動表訪問1次,被驅動表訪問2次)
Set linesize 1000
alter session set statistics_level=all ;
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n in(17, 19);
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.02 | 2019 |
| 1 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.02 | 2019 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 2 | 2 |00:00:00.01 | 8 |
|* 3 | TABLE ACCESS FULL| T2 | 2 | 1 | 2 |00:00:00.02 | 2011 |
-------------------------------------------------------------------------------------
2 - filter(("T1"."N"=17 OR "T1"."N"=19))
3 - filter("T1"."ID"="T2"."T1_ID")
--繼續換個語句,這次T2表被訪問1次(驅動表訪問1次,被驅動表訪問1次)
Set linesize 1000
alter session set statistics_level=all ;
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n = 19;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 1014 |
| 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 1014 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 8 |
|* 3 | TABLE ACCESS FULL| T2 | 1 | 1 | 1 |00:00:00.01 | 1006 |
-------------------------------------------------------------------------------------
2 - filter("T1"."N"=19)
3 - filter("T1"."ID"="T2"."T1_ID")
---接下來,T2表居然被訪問0次(驅動表訪問1次,被驅動表訪問0次)
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n = 999999999;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 | 7 |
| 1 | NESTED LOOPS | | 1 | 1 | 0 |00:00:00.01 | 7 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 0 |00:00:00.01 | 7 |
|* 3 | TABLE ACCESS FULL| T2 | 0 | 1 | 0 |00:00:00.01 | 0 |
-------------------------------------------------------------------------------------
2 - filter("T1"."N"=999999999)
3 - filter("T1"."ID"="T2"."T1_ID")
---到最後,不只是T2表被訪問0次,連T1表也訪問0次
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND 1=2;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
----------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 |
|* 1 | FILTER | | 1 | | 0 |00:00:00.01 |
| 2 | NESTED LOOPS | | 0 | 100 | 0 |00:00:00.01 |
| 3 | TABLE ACCESS FULL| T1 | 0 | 100 | 0 |00:00:00.01 |
|* 4 | TABLE ACCESS FULL| T2 | 0 | 1 | 0 |00:00:00.01 |
----------------------------------------------------------------------------
1 - filter(NULL IS NOT NULL)
4 - filter("T1"."ID"="T2"."T1_ID")
--分析T2表被訪問次數不同的原因
---解釋T2表為啥被訪問100次
select count(*) from t1;
COUNT(*)
----------
100
---解釋T2表為啥被訪問2次
select count(*) from t1 where t1.n in (17,19);
COUNT(*)
----------
2
---解釋T2表為啥被訪問1次
select count(*) from t1 where t1.n = 19;
COUNT(*)
----------
1
---解釋T2表為啥被訪問0次
select count(*) from t1 where t1.n = 999999999;
COUNT(*)
----------
0
未完待續:
2 hash join
使用限制最多,不支援>、<、<>、like
3 merge sort join
支援>、<不支援<>、like
--我們用設定statistics_level=all的方式來觀察如下表連線語句的執行計劃:
--T2表被訪問100次(驅動表訪問1次,被驅動表訪問100次)
--這個set linesize 1000對dbms_xplan.display_cursor還是有影響的,如果沒有設定,預設情況下的輸出,將會少了很多列,如BUFFERS等
Set linesize 1000
alter session set statistics_level=all ;
SELECT /*+ leading(t1) use_nl(t2)*/ *
FROM t1, t2
WHERE t1.id = t2.t1_id;
--略去記錄結果
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 100 |00:00:00.94 | 100K|
| 1 | NESTED LOOPS | | 1 | 100 | 100 |00:00:00.94 | 100K|
| 2 | TABLE ACCESS FULL| T1 | 1 | 100 | 100 |00:00:00.01 | 14 |
|* 3 | TABLE ACCESS FULL| T2 | 100 | 1 | 100 |00:00:00.94 | 100K|
-------------------------------------------------------------------------------------
3 - filter("T1"."ID"="T2"."T1_ID")
---換個語句,這次T2表被訪問2次(驅動表訪問1次,被驅動表訪問2次)
Set linesize 1000
alter session set statistics_level=all ;
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n in(17, 19);
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.02 | 2019 |
| 1 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.02 | 2019 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 2 | 2 |00:00:00.01 | 8 |
|* 3 | TABLE ACCESS FULL| T2 | 2 | 1 | 2 |00:00:00.02 | 2011 |
-------------------------------------------------------------------------------------
2 - filter(("T1"."N"=17 OR "T1"."N"=19))
3 - filter("T1"."ID"="T2"."T1_ID")
--繼續換個語句,這次T2表被訪問1次(驅動表訪問1次,被驅動表訪問1次)
Set linesize 1000
alter session set statistics_level=all ;
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n = 19;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 1014 |
| 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 1014 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 8 |
|* 3 | TABLE ACCESS FULL| T2 | 1 | 1 | 1 |00:00:00.01 | 1006 |
-------------------------------------------------------------------------------------
2 - filter("T1"."N"=19)
3 - filter("T1"."ID"="T2"."T1_ID")
---接下來,T2表居然被訪問0次(驅動表訪問1次,被驅動表訪問0次)
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND t1.n = 999999999;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 | 7 |
| 1 | NESTED LOOPS | | 1 | 1 | 0 |00:00:00.01 | 7 |
|* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 0 |00:00:00.01 | 7 |
|* 3 | TABLE ACCESS FULL| T2 | 0 | 1 | 0 |00:00:00.01 | 0 |
-------------------------------------------------------------------------------------
2 - filter("T1"."N"=999999999)
3 - filter("T1"."ID"="T2"."T1_ID")
---到最後,不只是T2表被訪問0次,連T1表也訪問0次
SELECT /*+ leading(t1) use_nl(t2) */ *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND 1=2;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
----------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.01 |
|* 1 | FILTER | | 1 | | 0 |00:00:00.01 |
| 2 | NESTED LOOPS | | 0 | 100 | 0 |00:00:00.01 |
| 3 | TABLE ACCESS FULL| T1 | 0 | 100 | 0 |00:00:00.01 |
|* 4 | TABLE ACCESS FULL| T2 | 0 | 1 | 0 |00:00:00.01 |
----------------------------------------------------------------------------
1 - filter(NULL IS NOT NULL)
4 - filter("T1"."ID"="T2"."T1_ID")
--分析T2表被訪問次數不同的原因
---解釋T2表為啥被訪問100次
select count(*) from t1;
COUNT(*)
----------
100
---解釋T2表為啥被訪問2次
select count(*) from t1 where t1.n in (17,19);
COUNT(*)
----------
2
---解釋T2表為啥被訪問1次
select count(*) from t1 where t1.n = 19;
COUNT(*)
----------
1
---解釋T2表為啥被訪問0次
select count(*) from t1 where t1.n = 999999999;
COUNT(*)
----------
0
2 hash join
使用限制最多,不支援>、<、<>、like
3 merge sort join
支援>、<不支援<>、like
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29135257/viewspace-2086443/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 建立連結串列兩種方法的區別
- Golang切片的三種簡單使用方式及區別Golang
- 三種表連線方式 最佳化總結
- 【程式設計】java jdbc/ojdbc 連結oracle的三種方式程式設計JavaJDBCOracle
- Oracle的三種表連線方式Oracle
- 總結下三種stl佇列的api區別佇列API
- “軟連結”和“硬連結”的區別
- 軟連結與硬連結的區別
- 硬連結和軟連結的區別
- URL的返回方式 —— 三種結構
- Linux網路連線的三種方式Linux
- 動態代理的兩種方式以及區別
- POSTMAN HTTP請求的四種方式區別PostmanHTTP
- javascript兩種宣告函式方式的區別JavaScript函式
- 純文字外鏈,帶連結外鏈,錨文字這三種有什麼區別?
- Python種匯入模組的三種方式總結Python
- vmware中三種網路連線方式
- 【SQL 效能優化】表的三種連線方式SQL優化
- Redis叢集的三種方式詳解(附優缺點及原理區別)Redis
- React | ref三種使用方式總結React
- String中三種加法的區別
- SQL Server 三種複製的區別SQLServer
- hibernate中建立session的兩種方式方式,區別在哪裡?Session
- PHP中資料型別轉換的三種方式PHP資料型別
- XSD中自定義型別的三種方式型別
- 【SQL 效能最佳化】表的三種連線方式SQL
- 從資料恢復角度分析iscsi、cifs、NFS三種儲存方式的區別資料恢復NFS
- 動態連結庫和靜態連結庫的區別
- (轉)編譯和連結的區別編譯
- 陣列和連結串列的區別陣列
- 常見的三種工廠模式區別模式
- Javascript中兩種方式定義函式的區別JavaScript函式
- 兩種方式建立sqlserver連結伺服器SQLServer伺服器
- 表的三種連線方式官方解釋及個人理解
- 使用者連線到oracle的三種驗證方式Oracle
- merge into三種表連線方式的效能比較(一)
- 記住Python變數型別的三種方式Python變數型別
- 軟連線與硬連結的區別,以及如何刪除軟連結