表的驱动顺序与性能

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

猜你喜欢

转载自blog.csdn.net/xxzhaobb/article/details/80918495