概述
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
- --use_nl,use_hash,use_merge的3种连接方式驱动与被驱动关系
- 一.HASH连接方式
- --建一个小表和一个大一些的表
- SQL> create table t1 as select * from dba_objects where rownum<11;
- Table created.
- SQL> create table t2 as select * from dba_objects;
- Table created.
- SQL> select count(1) from t1;
- COUNT(1)
- ----------
- 10
- SQL> select count(1) from t2;
- COUNT(1)
- ----------
- 75211
- --试验HASH,可以看出hash是存在驱动与被驱动关系,驱动表适合于两表间较小的一个,耗用更少的排序开销;
- SQL> select /*+ leading(t2) use_hash(t2,t1) */t1.status,t2.status
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id;
- STATUS STATUS
- ------- -------
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- 10 rows selected.
- --看到排序区中排序的开销为3439K;
- SQL> @allstat
- PLAN_TABLE_OUTPUT
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- SQL_ID 315bd4pgdyt86, child number 1
- -------------------------------------
- select /*+ leading(t2) use_hash(t2,t1) */t1.status,t2.status from t1,t2
- where t1.object_id=t2.object_id
- Plan hash value: 2959412835
- -------------------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
- -------------------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.08 | 1078 | 1071 | | | |
- |* 1 | HASH JOIN | | 1 | 10 | 10 |00:00:00.08 | 1078 | 1071 | 3439K| 1573K| 5617K (0)|
- | 2 | TABLE ACCESS FULL| T2 | 1 | 79628 | 75211 |00:00:00.02 | 1074 | 1071 | | | |
- | 3 | TABLE ACCESS FULL| T1 | 1 | 10 | 10 |00:00:00.01 | 4 | 0 | | | |
- -------------------------------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 25 rows selected.
- --而T1表为驱动表时,排序的开销为1206K比上面的3439K小得多;
- SQL> select /*+ leading(t1) use_hash(t2,t1) */t1.status,t2.status
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id;
- STATUS STATUS
- ------- -------
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- VALID VALID
- 10 rows selected.
- SQL> @allstat
- PLAN_TABLE_OUTPUT
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- SQL_ID 3zc11bg9gdq31, child number 1
- -------------------------------------
- select /*+ leading(t1) use_hash(t2,t1) */t1.status,t2.status from t1,t2
- where t1.object_id=t2.object_id
- Plan hash value: 1838229974
- -------------------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
- -------------------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.08 | 1078 | 1071 | | | |
- |* 1 | HASH JOIN | | 1 | 10 | 10 |00:00:00.08 | 1078 | 1071 | 1206K| 1206K| 1126K (0)|
- | 2 | TABLE ACCESS FULL| T1 | 1 | 10 | 10 |00:00:00.01 | 3 | 0 | | | |
- | 3 | TABLE ACCESS FULL| T2 | 1 | 79628 | 75211 |00:00:00.03 | 1075 | 1071 | | | |
- -------------------------------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 25 rows selected.
- --而ORACLE在预估COST时第一类的COST也是大于第2类,也就是默认O是会采用第2种方式;
- --第1类的COST为419,而第2类的COST预估为305;
- SQL> set auto traceonly
- SP2-0158: unknown SET autocommit option "traceonly"
- Usage: SET AUTO[COMMIT] { OFF | ON | IMM[EDIATE] | n }
- SQL> set autot traceonly exp
- SQL>
- SQL> select /*+ leading(t2) use_hash(t2,t1) */t1.status,t2.status
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 2959412835
- -----------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- -----------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 10 | 360 | | 419 (1)| 00:00:06 |
- |* 1 | HASH JOIN | | 10 | 360 | 2336K| 419 (1)| 00:00:06 |
- | 2 | TABLE ACCESS FULL| T2 | 79628 | 1399K| | 301 (1)| 00:00:04 |
- | 3 | TABLE ACCESS FULL| T1 | 10 | 180 | | 3 (0)| 00:00:01 |
- -----------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- SQL> select /*+ leading(t1) use_hash(t2,t1) */t1.status,t2.status
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 1838229974
- ---------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ---------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 10 | 360 | 305 (1)| 00:00:04 |
- |* 1 | HASH JOIN | | 10 | 360 | 305 (1)| 00:00:04 |
- | 2 | TABLE ACCESS FULL| T1 | 10 | 180 | 3 (0)| 00:00:01 |
- | 3 | TABLE ACCESS FULL| T2 | 79628 | 1399K| 301 (1)| 00:00:04 |
- ---------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- --HASH连接方式默认当然是采用后一种COST较小那类;
- SQL> select t1.status,t2.status
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id;
- Execution Plan
- ----------------------------------------------------------
- Plan hash value: 1838229974
- ---------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ---------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 10 | 360 | 305 (1)| 00:00:04 |
- |* 1 | HASH JOIN | | 10 | 360 | 305 (1)| 00:00:04 |
- | 2 | TABLE ACCESS FULL| T1 | 10 | 180 | 3 (0)| 00:00:01 |
- | 3 | TABLE ACCESS FULL| T2 | 79628 | 1399K| 301 (1)| 00:00:04 |
- ---------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 二.排序合并连接方式
- --可以看到无论是哪种表排在前面先执行,其开销都是一样的;也就是说明merge方式是不存在驱动与被驱动的区别关系 ;
- PLAN_TABLE_OUTPUT
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- SQL_ID 2yw072zjb9h5b, child number 1
- -------------------------------------
- select /*+ leading(t1) use_merge(t2,t1) */t1.status,t2.status from
- t1,t2 where t1.object_id=t2.object_id
- Plan hash value: 412793182
- --------------------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
- --------------------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.06 | 1077 | 1071 | | | |
- | 1 | MERGE JOIN | | 1 | 10 | 10 |00:00:00.06 | 1077 | 1071 | | | |
- | 2 | SORT JOIN | | 1 | 10 | 10 |00:00:00.01 | 3 | 0 | 2048 | 2048 | 2048 (0)|
- | 3 | TABLE ACCESS FULL| T1 | 1 | 10 | 10 |00:00:00.01 | 3 | 0 | | | |
- |* 4 | SORT JOIN | | 10 | 79628 | 10 |00:00:00.06 | 1074 | 1071 | 2675K| 740K| 2377K (0)|
- | 5 | TABLE ACCESS FULL| T2 | 1 | 79628 | 75211 |00:00:00.02 | 1074 | 1071 | | | |
- --------------------------------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- filter("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 28 rows selected.
- PLAN_TABLE_OUTPUT
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- SQL_ID csjsgn0hh4dr6, child number 1
- -------------------------------------
- select /*+ leading(t2) use_merge(t2,t1) */t1.status,t2.status from
- t1,t2 where t1.object_id=t2.object_id
- Plan hash value: 1792967693
- --------------------------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
- --------------------------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.09 | 1077 | 1071 | | | |
- | 1 | MERGE JOIN | | 1 | 10 | 10 |00:00:00.09 | 1077 | 1071 | | | |
- | 2 | SORT JOIN | | 1 | 79628 | 54 |00:00:00.09 | 1074 | 1071 | 2675K| 740K| 2377K (0)|
- | 3 | TABLE ACCESS FULL| T2 | 1 | 79628 | 75211 |00:00:00.02 | 1074 | 1071 | | | |
- |* 4 | SORT JOIN | | 54 | 10 | 10 |00:00:00.01 | 3 | 0 | 2048 | 2048 | 2048 (0)|
- | 5 | TABLE ACCESS FULL| T1 | 1 | 10 | 10 |00:00:00.01 | 3 | 0 | | | |
- --------------------------------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- filter("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 三.嵌套循环连接方式是影响最为明显的,buffers数相差了10倍之多;
- PLAN_TABLE_OUTPUT
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- SQL_ID 35g7vtpc63s04, child number 0
- -------------------------------------
- select /*+ leading(t1) use_nl(t2,t1) */t1.status,t2.status from t1,t2
- where t1.object_id=t2.object_id
- Plan hash value: 1967407726
- ----------------------------------------------------------------------------------------------
- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
- ----------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.11 | 10745 | 10710 |
- | 1 | NESTED LOOPS | | 1 | 10 | 10 |00:00:00.11 | 10745 | 10710 |
- | 2 | TABLE ACCESS FULL| T1 | 1 | 10 | 10 |00:00:00.01 | 4 | 0 |
- |* 3 | TABLE ACCESS FULL| T2 | 10 | 1 | 10 |00:00:00.11 | 10741 | 10710 |
- ----------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- PLAN_TABLE_OUTPUT
- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- SQL_ID 1a5dw45kqph9p, child number 0
- -------------------------------------
- select /*+ leading(t2) use_nl(t2,t1) */t1.status,t2.status from t1,t2
- where t1.object_id=t2.object_id
- Plan hash value: 4016936828
- ----------------------------------------------------------------------------------------------
- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
- ----------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.93 | 226K| 1071 |
- | 1 | NESTED LOOPS | | 1 | 10 | 10 |00:00:00.93 | 226K| 1071 |
- | 2 | TABLE ACCESS FULL| T2 | 1 | 79628 | 75211 |00:00:00.06 | 1075 | 1071 |
- |* 3 | TABLE ACCESS FULL| T1 | 75211 | 1 | 10 |00:00:00.74 | 225K| 0 |
- ----------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - dynamic sampling used for this statement (level=2)
- 25 rows selected.
- 小结:从以上可看出,影响大到小的顺序为nl->hash->merge(不影响);
- 应用:日常工作环境中经常可看到,由于nl方式不当而应使用hash的案例,毕竟NL对数据量的大小影响是最为敏感;
- 而ORACLE选择NL方式并没有错,错就错在预估值那里,所以当用explain plan for....,autot等方式看并不能看出问题;
- 当通过running time的统计信息收集然后select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
- 就会发现真正的原因是预估值与实际值的问题相差过大导致的;
- 在这种情况下执行计划的绑定是比较实用和有效的;
http://blog.csdn.net/launch_225/article/details/27859219
最后
以上就是着急花卷为你收集整理的use_nl,use_hash,use_merge的3种连接方式驱动与被驱动关系的全部内容,希望文章能够帮你解决use_nl,use_hash,use_merge的3种连接方式驱动与被驱动关系所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复