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
相关推荐
本文将详细介绍三种主要的表连接方式:嵌套循环连接(Nested Loop Join,简称NL Join)、排序合并连接(Sort Merge Join,简称SM Join)以及散列连接(Hash Join)。我们将探讨它们的特点、优势与劣势,以便于在实际...
NESTED LOOP是一种基本的表连接方式,适用于被连接的数据子集较小的情况。在nested loop连接中,驱动表满足条件结果集不大,被驱动表的连接字段要有索引,这样就走nested loop。如果驱动表返回记录太多,就不适合...
在优化SQL查询时,主要涉及三种连接方法:嵌套循环连接(USE_NL)、排列合并连接(USE_MERGE)和哈希连接(USE_HASH)。以下是对这些连接方式的详细说明: 1. **嵌套循环连接(USE_NL)** - 在嵌套循环连接中,...
Oracle提供了三种主要的表连接方式:NESTED LOOP JOIN、HASH JOIN和SORT MERGE JOIN。每种方法都有其独特的应用场景和性能特点。 #### NESTED LOOP JOIN NESTED LOOP JOIN是一种简单的连接方式,适用于连接的数据...
- `NO_USE_NL`:指示不使用嵌套循环连接。 4. **并行执行提示** - `PARALLEL`:指示查询使用并行执行。 - `NO_PARALLEL`:指示查询不使用并行执行。 - `PQ_DISTRIBUTE`:指示并行查询的分布策略。 5. **查询...
`USE_MERGE` 强制使用排序合并连接,而 `USE_NL` 使用嵌套循环连接。 2. **连接操作**: - **Nested Loop Join (NLJ)**:适合于小表连接大表的情况,每次从驱动表取出一条记录,然后在另一个表中查找匹配记录。 -...
- **NL_AJ**、**HASH_AJ**、**MERGE_AJ**:分别指定嵌套循环、哈希和合并连接方式。 - **USE_HASH**、**USE_MERGE**、**USE_NL**:分别指定使用哈希、合并或嵌套循环连接。 - **NO_USE_HASH**、**NO_USE_MERGE**、**...
3. `use_nl_with_index`:这个hint强制CBO使用嵌套循环连接(NLJ),并将特定表作为内部表,前提是CBO能找到匹配的索引键值。这在某些特定场景下可以提高查询效率。 4. `CARDINALITY`:这个hint允许用户指定查询...
3. **NESTED LOOPS, MERGE JOIN, AND HASH JOIN**:这三个Hint分别对应三种不同的连接算法。`NESTED LOOPS`适合小表连接大表,`MERGE JOIN`适用于两个已排序的表,而`HASH JOIN`适用于处理大规模数据集。 4. **...
Oracle数据库在处理表之间的连接操作时提供了三种主要的连接方式:Nested Loop Join、Hash Join以及Sort Merge Join。这些连接方式各有特点,适用于不同的情景,理解它们的工作原理和适用条件对于SQL查询优化至关...
6.4.1 use_hash,use_nl和use_merge hint 127 6.4.2 no_use_hash hint 132 6.4.3 no_use_merge hint 133 6.4.4 no_use_nl hint 133 6.5 并行执行相关的hint 134 6.5.1 parallel hint 134 6.5.2 no_parallel hint 134...
Oracle SQL Hints是一种在Oracle数据库中用于优化SQL语句执行计划的辅助手段。通过在SQL语句中嵌入特定的指令,即HINT,可以向Oracle优化器强制指示使用特定的访问路径、关联方法等,以便绕过优化器的默认选择,从而...
6.4.1 use_hash,use_nl和use_merge hint 127 6.4.2 no_use_hash hint 132 6.4.3 no_use_merge hint 133 6.4.4 no_use_nl hint 133 6.5 并行执行相关的hint 134 6.5.1 parallel hint 134 6.5.2 no_parallel hint 134...
- USE_HASH、NO_USE_HASH等用于开启或禁用特定的join优化方法。 概要数据提示:这类提示用于向优化器提供额外的统计信息。 - OPTIMIZER_FEATURES_ENABLE:指定优化器应该使用哪个版本的特性。 - OPT_PARAM:设置...
- **使用 `USE_MERGE` 提示**:指定使用 `MERGE JOIN` 连接方式。 - **使用 `USE_HASH` 提示**:指定使用 `HASH JOIN` 连接方式。 - **使用 `INDEX` 提示**:指定使用特定的索引来访问表。 尽管HINTs提供了一种直接...
USE_MERGE(使用MERGE JOIN方式联合) USE_HASH(使用HASH JOIN方式联合) 索引提示: INDEX(TABLE INDEX)(使用提示的表索引进行查询) 其它高级提示(如并行处理等等) 1.5 索引的规则: 建立...
- **`/*+ USE_NL (表名) */`**:强制使用嵌套循环连接方法。 - **`/*+ NO_INDEX (表名) */`**:禁止使用任何索引,只能进行全表扫描。 ##### 2.2 连接方法暗示 连接方法暗示用于控制不同表之间的连接方式,常用的...
列举几种表连接方式** - **NESTED LOOP (NL)**: 适用于其中一张表的查询结果非常小,或者连接条件较为复杂(如使用 `NOT IN` 等)的情况。这种连接方式先处理较小的表,然后对于每一条记录,在较大的表中寻找匹配...