本次试验用于探究 嵌套循环,哈希连接,排序合并这三种类型下,驱动表顺序的研究。
一、嵌套循环(Nested Loops Join)
1.t1为主表,t2为从表(t1表先访问)
select /*+leading(t1) use_nl(t2)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19;
SCOTT@ orclselect * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID 4j97842y306uk, child number 0 ------------------------------------- select /*+leading(t1) use_nl(t2)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19 Plan hash value: 1967407726 ------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------- | 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:00.01 | 1014 | PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |* 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"=19) 3 - filter("T1"."ID"="T2"."T1_ID") Note PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ----- - dynamic sampling used for this statement 25 rows selected.2.t1为从表,t2为主表时(t2表先访问)
select /*+leading(t2) use_nl(t1)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19; SCOTT@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID 6uqqzgzs7y35f, child number 0 ------------------------------------- select /*+leading(t2) use_nl(t1)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19 Plan hash value: 4016936828 ------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------- | 1 | NESTED LOOPS | | 1 | 1 | 1 |00:00:02.75 | 701K| PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 2 | TABLE ACCESS FULL| T2 | 1 | 102K| 100K|00:00:00.30 | 1006 | |* 3 | TABLE ACCESS FULL| T1 | 100K| 1 | 1 |00:00:01.98 | 700K| ------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter(("T1"."N"=19 AND "T1"."ID"="T2"."T1_ID")) Note ----- PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - dynamic sampling used for this statement 24 rows selected.
3.结论:
Starts | Buffers | ||||
第一次 | 主 | T1 | 1 | 8 | 1014 |
从 | T2 | 1 | 1006 | ||
第二次 | 主 | T2 | 1 | 1006 | 701K |
从 | T1 | 100K | 700k |
3.1 根据驱动表的访问顺序不同,Buffers产生的差异是巨大的。
3.2 T1为驱动表时,T2被访问1次。而T2为驱动表时,T1被访问10000次。
3.3 循环嵌套表应注意驱动表的顺序。小的结果集先访问,大的结果集后访问。才能使得被驱动表的访问次数降到最低,从而提升性能。
二、哈希连接(Hash Join)select /*+leading(t1) use_hash(t2)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19; SCOTT@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID c7tdkmk355c8n, child number 0 ------------------------------------- select /*+leading(t1) use_hash(t2)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19 Plan hash value: 1838229974 ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- |* 1 | HASH JOIN | | 1 | 1 | 1 |00:00:00.74 | 1013 | 741K| 741K| 328K (0)| |* 2 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 7 | | | | PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 3 | TABLE ACCESS FULL| T2 | 1 | 102K| 100K|00:00:00.20 | 1006 | | | | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."T1_ID") 2 - filter("T1"."N"=19) Note ----- PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - dynamic sampling used for this statement 24 rows selected.
2.t1为从表,t2为主表时(t2表先访问)
select /*+leading(t2) use_hash(t1)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19; SCOTT@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID 5mszurvg6jrxx, child number 0 ------------------------------------- select /*+leading(t2) use_hash(t1)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19 Plan hash value: 2959412835 ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- |* 1 | HASH JOIN | | 1 | 1 | 1 |00:00:00.89 | 1013 | 9471K| 1956K| 10M (0)| | 2 | TABLE ACCESS FULL| T2 | 1 | 102K| 100K|00:00:00.20 | 1005 | | | | PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |* 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"=19) Note ----- PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - dynamic sampling used for this statement 24 rows selected.
3.结论
Starts | Buffers | Used-Mem | ||||
第一次 | 主 | T1 | 1 | 7 | 1013 | 328K |
从 | T2 | 1 | 1006 | |||
第二次 | 主 | T2 | 102K | 1005 | 1013 | 10M |
从 | T1 | 1 | 8 |
3.1 根据驱动表的访问顺序不同,Buffers相同,但Used-Mem的差别很大。
三、排序合并(Merge Sort Join)
1.t1为主表,t2为从表(t1表先访问)select /*+leading(t1) use_merge(t2)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19; SCOTT@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID aw04dp4k1q1x7, 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 | ----------------------------------------------------------------------------------------------------------------- | 1 | MERGE JOIN | | 1 | 1 | 1 |00:00:00.43 | 1012 | | | | | 2 | SORT JOIN | | 1 | 1 | 1 |00:00:00.01 | 7 | 2048 | 2048 | 2048 (0)| PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |* 3 | TABLE ACCESS FULL| T1 | 1 | 1 | 1 |00:00:00.01 | 7 | | | | |* 4 | SORT JOIN | | 1 | 102K| 1 |00:00:00.43 | 1005 | 9124K| 1177K| 8110K (0)| | 5 | TABLE ACCESS FULL| T2 | 1 | 102K| 100K|00:00:00.20 | 1005 | | | | ----------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - filter("T1"."N"=19) 4 - access("T1"."ID"="T2"."T1_ID") filter("T1"."ID"="T2"."T1_ID") PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Note ----- - dynamic sampling used for this statement 27 rows selected.2.t1为从表,t2为主表时(t2表先访问)
select /*+leading(t2) use_merge(t1)*/* from t1,t2 where t1.id = t2.t1_id and t1.n = 19; SCOTT@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID 79yag6bg8z2zr, 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 | ----------------------------------------------------------------------------------------------------------------- | 1 | MERGE JOIN | | 1 | 1 | 1 |00:00:00.86 | 1012 | | | | | 2 | SORT JOIN | | 1 | 102K| 20 |00:00:00.86 | 1005 | 9124K| 1177K| 8110K (0)| PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 3 | TABLE ACCESS FULL| T2 | 1 | 102K| 100K|00:00:00.20 | 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") filter("T1"."ID"="T2"."T1_ID") 5 - filter("T1"."N"=19) PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Note ----- - dynamic sampling used for this statement 27 rows selected.3.结论
Starts | Buffers | Used-Mem | |||
第一次 | 主 | SORT1 | 1 | 1 | 2048 |
从 | SORT2 | 1 | 102K | 8110 | |
第二次 | 主 | SORT2 | 1 | 102K | 8110 |
从 | SORT1 | 1 | 1 | 2048 |