为了弥补嵌套循环连接的不足,即在连接数据量比较大时,为了缩减嵌套循环连接中的大量随机读取,以及连接列不存在索引时,可以替代嵌套循环连接。
但是为了实现表连接,它必须要先对两个表中的将要执行连接的行进行排序。虽然这种方式提高了连接效率,但由于排序的存在,增加了连接的代价。如果能够快速的完成排序操作(排序内存空间大小(sort_area_size),并行),那么在处理大数据量时,排序合并连接将是不错的选择。
如果在连接列上有索引,并且利用该索引读取数据,由于索引是有序的,可以消除外部行源的排序操作。
排序合并连接没有嵌套循环连接中驱动表的概念。
- SQL> create table t1 as select * from dba_objects;
- 表已创建。
- SQL> create table t2 as select * from dba_objects;
- 表已创建。
- SQL> set autot traceonly
- SQL> set linesize 120
- SQL> select /*+ use_merge(t1,t2) +*/ t1.object_id,t1.object_name,t2.object_name
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id;
- 已选择50425行。
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 412793182
- ------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- ------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 53430 | 8244K| | 2379 (2)| 00:00:29 |
- | 1 | MERGE JOIN | | 53430 | 8244K| | 2379 (2)| 00:00:29 |
- | 2 | SORT JOIN | | 53430 | 4122K| 9304K| 1152 (2)| 00:00:14 |
- | 3 | TABLE ACCESS FULL| T1 | 53430 | 4122K| | 161 (2)| 00:00:02 |
- |* 4 | SORT JOIN | | 57436 | 4431K| 9M| 1227 (2)| 00:00:15 |
- | 5 | TABLE ACCESS FULL| T2 | 57436 | 4431K| | 161 (2)| 00:00:02 |
- ------------------------------------------------------------------------------------
- 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
- 统计信息
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 1396 consistent gets
- 0 physical reads
- 0 redo size
- 3166055 bytes sent via SQL*Net to client
- 37356 bytes received via SQL*Net from client
- 3363 SQL*Net roundtrips to/from client
- 2 sorts (memory)
- 0 sorts (disk)
- 50425 rows processed
- SQL> create index ind_t1_object_id on t1(object_id);
- 索引已创建。
- SQL> create index ind_t2_object_id on t2(object_id);
- 索引已创建。
- /**由于索引是有序的,可以消除外部行源的排序操作*/
- SQL> select /*+ use_merge(t1,t2) +*/ t1.object_id,t1.object_name,t2.object_name
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id ;
- 已选择50425行。
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 3739185171
- ---------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- ---------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 53430 | 8244K| | 2031 (1)| 00:00:25 |
- | 1 | MERGE JOIN | | 53430 | 8244K| | 2031 (1)| 00:00:25 |
- | 2 | TABLE ACCESS BY INDEX ROWID| T2 | 57436 | 4431K| | 879 (1)| 00:00:11 |
- | 3 | INDEX FULL SCAN | IND_T2_OBJECT_ID | 57436 | | | 125 (2)| 00:00:02 |
- |* 4 | SORT JOIN | | 53430 | 4122K| 9304K| 1152 (2)| 00:00:14 |
- | 5 | TABLE ACCESS FULL | T1 | 53430 | 4122K| | 161 (2)| 00:00:02 |
- ---------------------------------------------------------------------------------------------------------
- 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
- 统计信息
- ----------------------------------------------------------
- 8 recursive calls
- 0 db block gets
- 8384 consistent gets
- 117 physical reads
- 0 redo size
- 3166055 bytes sent via SQL*Net to client
- 37356 bytes received via SQL*Net from client
- 3363 SQL*Net roundtrips to/from client
- 3 sorts (memory)
- 0 sorts (disk)
- 50425 rows processed
- SQL> select /*+ use_merge(t1,t2) index(t1 ind_t1_object_id) +*/ t1.object_id,t1.object_name,t2.object_name
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id ;
- 已选择50425行。
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 3856170417
- ---------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- ---------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 53430 | 8244K| | 2107 (1)| 00:00:26 |
- | 1 | MERGE JOIN | | 53430 | 8244K| | 2107 (1)| 00:00:26 |
- | 2 | TABLE ACCESS BY INDEX ROWID| T1 | 53430 | 4122K| | 881 (1)| 00:00:11 |
- | 3 | INDEX FULL SCAN | IND_T1_OBJECT_ID | 53430 | | | 125 (2)| 00:00:02 |
- |* 4 | SORT JOIN | | 57436 | 4431K| 9M| 1227 (2)| 00:00:15 |
- | 5 | TABLE ACCESS FULL | T2 | 57436 | 4431K| | 161 (2)| 00:00:02 |
- ---------------------------------------------------------------------------------------------------------
- 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
- 统计信息
- ----------------------------------------------------------
- 7 recursive calls
- 0 db block gets
- 8386 consistent gets
- 0 physical reads
- 0 redo size
- 3166055 bytes sent via SQL*Net to client
- 37356 bytes received via SQL*Net from client
- 3363 SQL*Net roundtrips to/from client
- 3 sorts (memory)
- 0 sorts (disk)
- 50425 rows processed
- SQL> select /*+ use_merge(t1,t2) index(t1 ind_t1_object_id) index(t2 ind_t2_object_id) +*/ t1.object_id,t1.object_name,
- 2.object_name
- 2 from t1,t2
- 3 where t1.object_id=t2.object_id ;
- 已选择50425行。
- 执行计划
- ----------------------------------------------------------
- Plan hash value: 3655247094
- ----------------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- ----------------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 53430 | 8244K| | 2750 (1)| 00:00:34 |
- | 1 | MERGE JOIN | | 53430 | 8244K| | 2750 (1)| 00:00:34 |
- | 2 | TABLE ACCESS BY INDEX ROWID | T2 | 57436 | 4431K| | 879 (1)| 00:00:11 |
- | 3 | INDEX FULL SCAN | IND_T2_OBJECT_ID | 57436 | | | 125 (2)| 00:00:02 |
- |* 4 | SORT JOIN | | 53430 | 4122K| 9304K| 1872 (1)| 00:00:23 |
- | 5 | TABLE ACCESS BY INDEX ROWID| T1 | 53430 | 4122K| | 881 (1)| 00:00:11 |
- | 6 | INDEX FULL SCAN | IND_T1_OBJECT_ID | 53430 | | | 125 (2)| 00:00:02 |
- ----------------------------------------------------------------------------------------------------------
- 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
- 统计信息
- ----------------------------------------------------------
- 7 recursive calls
- 0 db block gets
- 8551 consistent gets
- 0 physical reads
- 0 redo size
- 3166055 bytes sent via SQL*Net to client
- 37356 bytes received via SQL*Net from client
- 3363 SQL*Net roundtrips to/from client
- 3 sorts (memory)
- 0 sorts (disk)
- 50425 rows processed