1 nested Loops join
--t1 表先访问的情况
alter session set statistics_level=all;
select /*+ leading (t1) use_nl(t2)*/* from t1,t2 where t1.id=t2.id and t1.n=9;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
ZBB@test>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------
SQL_ID 2827rrw9myady, child number 0
-------------------------------------
select /*+ leading (t1) use_nl(t2)*/* from t1,t2 where t1.id=t2.id and
t1.n=9
Plan hash value: 1967407726
-------------------------------------------------------------------------------------
| 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 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("T1"."N"=9)
3 - filter("T1"."ID"="T2"."ID")
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
26 rows selected.
-- t2表先访问的情况
select /*+ leading (t2) use_nl(t1)*/* from t1,t2 where t1.id=t2.id and t1.n=9;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
ZBB@test>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
SQL_ID 90duak5uvfgqb, child number 0
-------------------------------------
select /*+ leading (t2) use_nl(t1)*/* from t1,t2 where t1.id=t2.id and
t1.n=9
Plan hash value: 4016936828
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.74 | 701K|
| 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.74 | 701K|
| 2 | TABLE ACCESS FULL| T2 | 1 | 111K| 99999 |00:00:00.01 | 1006 |
|* 3 | TABLE ACCESS FULL| T1 | 99999 | 1 | 1 |00:00:00.70 | 699K|
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(("T1"."N"=9 AND "T1"."ID"="T2"."ID"))
Note
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
- dynamic sampling used for this statement (level=2)
25 rows selected.
从上面的两次执行的结果,buffers是不一样的。所以,再nested loops join 中,表的驱动顺序对性能有着巨大的影响。
2 hash join
-- t1作为驱动表
set linesize 1000
alter session set statistics_level=all;
select /*+ leading(t1) use_hash(t2)*/ * from t1,t2 where t1.id=t2.t1_id and t1.n=9;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
ZBB@test>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
SQL_ID ga78zwrw60qvx, child number 0
-------------------------------------
select /*+ leading(t1) use_hash(t2)*/ * from t1,t2 where t1.id=t2.t1_id
and t1.n=9
Plan hash value: 1838229974
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.05 | 1013 | | | |
|* 1 | HASH JOIN | | 1 | 1 | 1 |00:00:00.05 | 1013 | 960K| 960K| 408K (0)|
|* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 7 | | | |
| 3 | TABLE ACCESS FULL| T2 | 1 | 111K| 99999 |00:00:00.01 | 1006 | | | |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."ID"="T2"."T1_ID")
2 - filter("T1"."N"=9)
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
26 rows selected.
-- t2作为驱动表
select /*+ leading(t2) use_hash(t1)*/ * from t1,t2 where t1.id=t2.t1_id and t1.n=9;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
ZBB@test>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------
SQL_ID 0c4q2ts1cdtqr, child number 0
-------------------------------------
select /*+ leading(t2) use_hash(t1)*/ * from t1,t2 where t1.id=t2.t1_id
and t1.n=9
Plan hash value: 2959412835
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.07 | 1013 | | | |
|* 1 | HASH JOIN | | 1 | 1 | 1 |00:00:00.07 | 1013 | 11M| 2469K| 16M (0)|
| 2 | TABLE ACCESS FULL| T2 | 1 | 111K| 99999 |00:00:00.01 | 1005 | | | |
|* 3 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 8 | | | |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T1"."ID"="T2"."T1_ID")
3 - filter("T1"."N"=9)
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
26 rows selected.
总结OMem列,内存的消耗是不一样的,小表驱动大表的时候,消耗较小的内存。所以,在hash join中,表的驱动顺序对性能是有影响的。
3 merge sort join
-- 首先是 t1表是驱动表
set linesize 1000
alter session set statistics_level=all;
select /*+ leading(t1) use_merge(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'));
ZBB@test>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
SQL_ID 3nvbf956a8azg, child number 0
-------------------------------------
select /*+ leading(t1) use_merge(t2)*/ * from t1,t2 where
t1.id=t2.t1_id and t1.n=19
Plan hash value: 412793182
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.05 | 1012 | | | |
| 1 | MERGE JOIN | | 1 | 1 | 1 |00:00:00.05 | 1012 | | | |
| 2 | SORT JOIN | | 1 | 1 | 1 |00:00:00.01 | 7 | 2048 | 2048 | 2048 (0)|
|* 3 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 7 | | | |
|* 4 | SORT JOIN | | 1 | 111K| 1 |00:00:00.05 | 1005 | 9762K| 1209K| 8677K (0)|
| 5 | TABLE ACCESS FULL| T2 | 1 | 111K| 99999 |00:00:00.02 | 1005 | | | |
-----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("T1"."N"=19)
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------
4 - access("T1"."ID"="T2"."T1_ID")
filter("T1"."ID"="T2"."T1_ID")
Note
-----
- dynamic sampling used for this statement (level=2)
29 rows selected.
-- 使用t2作为驱动表
select /*+ leading(t2) use_merge(t1)*/ * from t1,t2 where t1.id=t2.t1_id and t1.n=19;
select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
ZBB@test>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------
SQL_ID ddh3jpabkvm5x, child number 0
-------------------------------------
select /*+ leading(t2) use_merge(t1)*/ * from t1,t2 where
t1.id=t2.t1_id and t1.n=19
Plan hash value: 1792967693
-----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.07 | 1012 | | | |
| 1 | MERGE JOIN | | 1 | 1 | 1 |00:00:00.07 | 1012 | | | |
| 2 | SORT JOIN | | 1 | 111K| 20 |00:00:00.07 | 1005 | 9762K| 1209K| 8677K (0)|
| 3 | TABLE ACCESS FULL| T2 | 1 | 111K| 99999 |00:00:00.02 | 1005 | | | |
|* 4 | SORT JOIN | | 20 | 1 | 1 |00:00:00.01 | 7 | 2048 | 2048 | 2048 (0)|
|* 5 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 7 | | | |
-----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."ID"="T2"."T1_ID")
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------
filter("T1"."ID"="T2"."T1_ID")
5 - filter("T1"."N"=19)
Note
-----
- dynamic sampling used for this statement (level=2)
29 rows selected.
从上面的执行计划看,内存方面的开销是一样的。所以,当使用merge sort join的时候,表的驱动顺序对性能毫无影响。
END