博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表)
阅读量:6840 次
发布时间:2019-06-26

本文共 9810 字,大约阅读时间需要 32 分钟。

swap_join_inputs是针对哈希连接的hint,它的含义是让优化器交换原哈希连接的驱动表和被驱动表的顺序,即在依然走哈希连接的情况下让原哈希连接的驱动表变被驱动表,让原哈希连接的被驱动表变为驱动表。

注意,在swap_join_inputs hint中指定的目标表应该是原哈希连接中的被驱动表,否则oracle会忽略该hint。

/*+ swap_join_inputs(原哈希连接的被驱动表) */

其使用范例如下:

1
2
select 
/*+ leading(dept) use_hash(emp) swap_join_intputs(emp) */ * 
from 
emp,dept 
where
emp.deptno=dept.deptno

测试案例:

1
2
3
4
5
6
SCOTT@ORA12C> 
create 
table 
t1 
as 
select 
from 
dba_objects 
where 
rownum<2;
Table 
created.
SCOTT@ORA12C> 
create 
table 
t2 
as 
select 
from 
dba_objects 
where 
rownum<12;
Table 
created.
SCOTT@ORA12C> 
create 
table 
t3 
as 
select 
from 
dba_objects 
where 
rownum<22;
Table 
created.

收集统计信息:

1
2
3
4
5
6
SCOTT@ORA12C> 
exec 
dbms_stats.gather_table_stats(ownname => 
'SCOTT'
,tabname => 
'T1'
,estimate_percent => 100,
cascade 
=> 
true
,method_opt => 
'for all columns size 1'
,no_invalidate => 
false
);
PL/SQL 
procedure 
successfully completed.
SCOTT@ORA12C> 
exec 
dbms_stats.gather_table_stats(ownname => 
'SCOTT'
,tabname => 
'T2'
,estimate_percent => 100,
cascade 
=> 
true
,method_opt => 
'for all columns size 1'
,no_invalidate => 
false
);
PL/SQL 
procedure 
successfully completed.
SCOTT@ORA12C> 
exec 
dbms_stats.gather_table_stats(ownname => 
'SCOTT'
,tabname => 
'T3'
,estimate_percent => 100,
cascade 
=> 
true
,method_opt => 
'for all columns size 1'
,no_invalidate => 
false
);
PL/SQL 
procedure 
successfully completed.

3个表的记录如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SCOTT@ORA12C> 
select 
count
(*) 
from 
t1;
 
COUNT
(*)
-----------------
1
1 row selected.
SCOTT@ORA12C> 
select 
count
(*) 
from 
t2;
 
COUNT
(*)
-----------------
       
11
1 row selected.
SCOTT@ORA12C> 
select 
count
(*) 
from 
t3;
 
COUNT
(*)
-----------------
       
21
1 row selected.

现在我们来让表T2和T3做哈希连接,由于T3表的记录数比T2表的记录数多,所以这里指定T3为哈希连接的被驱动表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
select 
/*+ ordered use_hash(t3) */ t2.object_name,t3.object_type
  
2  
from 
t2,t3 
where 
t2.object_id=t3.object_id;
Execution Plan
----------------------------------------------------------
Plan hash value: 1730954469
---------------------------------------------------------------------------
| Id  | Operation   | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time  
|
---------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT   |  |    11 |   220 |6   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN   
|  |    11 |   220 |6   (0)| 00:00:01 |
|   2 |   
TABLE 
ACCESS 
FULL
| T2   |    11 |   110 |3   (0)| 00:00:01 |
|   3 |   
TABLE 
ACCESS 
FULL
| T3   |    21 |   210 |3   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID"
)

可以看到,上述SQL的执行计划现在走的是哈希连接,并且被驱动表示表T3.

如果我们想让哈希连接的被驱动表由T3变成T2,可以在上述sql加入swap_join_inputs hint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
select 
/*+ ordered use_hash(t3) swap_join_inputs(t3) */ t2.object_name,t3.object_type
  
2  
from 
t2,t3 
where 
t2.object_id=t3.object_id;
Execution Plan
----------------------------------------------------------
Plan hash value: 1723280936
---------------------------------------------------------------------------
| Id  | Operation   | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time  
|
---------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT   |  |    11 |   220 |6   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN   
|  |    11 |   220 |6   (0)| 00:00:01 |
|   2 |   
TABLE 
ACCESS 
FULL
| T3   |    21 |   210 |3   (0)| 00:00:01 |
|   3 |   
TABLE 
ACCESS 
FULL
| T2   |    11 |   110 |3   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID"
)

用leading(t3) use_hash(t2)也可以同样达到目的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
select 
/*+ leading(t3) use_hash(t2) */ t2.object_name,t3.object_type
  
2  
from 
t2,t3 
where 
t2.object_id=t3.object_id;
Execution Plan
----------------------------------------------------------
Plan hash value: 1723280936
---------------------------------------------------------------------------
| Id  | Operation   | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time  
|
---------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT   |  |    11 |   220 |6   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN   
|  |    11 |   220 |6   (0)| 00:00:01 |
|   2 |   
TABLE 
ACCESS 
FULL
| T3   |    21 |   210 |3   (0)| 00:00:01 |
|   3 |   
TABLE 
ACCESS 
FULL
| T2   |    11 |   110 |3   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID"
)

由此可见在两个表关联的时候,可以用其他hint代替swap_join_inputs来达到相同的目的:

那么多表关联呢:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
select 
/*+ ordered use_hash(t3) */ t1.owner,t2.object_name,t3.object_type
  
2  
from 
t2,t3,t1 
where 
t2.object_id=t3.object_id 
and 
t1.object_type=t3.object_type;
Execution Plan
----------------------------------------------------------
Plan hash value: 98820498
----------------------------------------------------------------------------
| Id  | Operation    | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time   
|
----------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT    |   | 4 |   120 | 9   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN    
|   | 4 |   120 | 9   (0)| 00:00:01 |
|*  2 |   HASH 
JOIN    
|   |11 |   220 | 6   (0)| 00:00:01 |
|   3 |    
TABLE 
ACCESS 
FULL
| T2   |11 |   110 | 3   (0)| 00:00:01 |
|   4 |    
TABLE 
ACCESS 
FULL
| T3   |21 |   210 | 3   (0)| 00:00:01 |
|   5 |   
TABLE 
ACCESS 
FULL 
| T1   | 1 |10 | 3   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T1"
.
"OBJECT_TYPE"
=
"T3"
.
"OBJECT_TYPE"
)
   
2 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID"

可以看到,现在上述sql的执行计划是先由表T2和表T3做哈希连接,然后将他们做哈希连接的连接结果集再和表T1做一次哈希连接。

表T1的记录数为1,表T2的记录数为11,表T3的记录数为21,所以当表的T2和T3做哈希连接时,记录数多的表T3应该是被驱动表,这是因为我们在上述sql中使用了ordered hint和use_hash HINT指定表T3作为表T2和T3连接的时的被驱动表,所以oracle这里选择了表T2和T3做哈希连接,并且选择了表T3作为该哈希连接的被驱动表,这是没有问题的,现在问题在于表T1的记录数仅为1,所以当表T2和T3做哈希连接的结果再和表T1做哈希连接时,表T1应该是驱动表,而不是在上述执行计划里显示的那样作为第二个哈希连接的被驱动表。

使用下面HINT:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
select 
/*+ ordered use_hash(t3) */ t1.owner,t2.object_name,t3.object_type
  
2  
from 
t1,t2,t3 
where 
t2.object_id=t3.object_id 
and 
t1.object_type=t3.object_type;
Execution Plan
----------------------------------------------------------
Plan hash value: 38266800
------------------------------------------------------------------------------
| Id  | Operation      | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time     
|
------------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT      |      |   4 | 120 |   9   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN      
|      |   4 | 120 |   9   (0)| 00:00:01 |
|   2 |   MERGE 
JOIN 
CARTESIAN|      |  11 | 220 |   6   (0)| 00:00:01 |
|   3 |    
TABLE 
ACCESS 
FULL  
| T1   |   1 |  10 |   3   (0)| 00:00:01 |
|   4 |    BUFFER SORT      |      |  11 | 110 |   3   (0)| 00:00:01 |
|   5 |     
TABLE 
ACCESS 
FULL 
| T2   |  11 | 110 |   3   (0)| 00:00:01 |
|   6 |   
TABLE 
ACCESS 
FULL   
| T3   |  21 | 210 |   3   (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID" 
AND
      
"T1"
.
"OBJECT_TYPE"
=
"T3"
.
"OBJECT_TYPE"
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
select 
/*+ leading(t1) use_hash(t3) */ t1.owner,t2.object_name,t3.object_type
  
2  
from 
t1,t2,t3 
where 
t2.object_id=t3.object_id 
and 
t1.object_type=t3.object_type;
Execution Plan
----------------------------------------------------------
Plan hash value: 2308542799
----------------------------------------------------------------------------
| Id  | Operation    | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time   
|
----------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT    |   | 7 |   210 | 9   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN    
|   | 7 |   210 | 9   (0)| 00:00:01 |
|*  2 |   HASH 
JOIN    
|   | 7 |   140 | 6   (0)| 00:00:01 |
|   3 |    
TABLE 
ACCESS 
FULL
| T1   | 1 |10 | 3   (0)| 00:00:01 |
|   4 |    
TABLE 
ACCESS 
FULL
| T3   |21 |   210 | 3   (0)| 00:00:01 |
|   5 |   
TABLE 
ACCESS 
FULL 
| T2   |11 |   110 | 3   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID"
)
   
2 - access(
"T1"
.
"OBJECT_TYPE"
=
"T3"
.
"OBJECT_TYPE"
)

加入以下hint,就解决:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT 
/*+ ordered use_hash(t3) swap_join_inputs(t1) */
 
t1.owner, t2.object_name, t3.object_type
  
FROM 
t2, t3, t1
 
WHERE 
t2.object_id = t3.object_id
  
5     
AND 
t1.object_type = t3.object_type;
Execution Plan
----------------------------------------------------------
Plan hash value: 3071514789
----------------------------------------------------------------------------
| Id  | Operation    | 
Name 
Rows  
| Bytes | Cost (%CPU)| 
Time   
|
----------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT    |   | 4 |   120 | 9   (0)| 00:00:01 |
|*  1 |  HASH 
JOIN    
|   | 4 |   120 | 9   (0)| 00:00:01 |
|   2 |   
TABLE 
ACCESS 
FULL 
| T1   | 1 |10 | 3   (0)| 00:00:01 |
|*  3 |   HASH 
JOIN    
|   |11 |   220 | 6   (0)| 00:00:01 |
|   4 |    
TABLE 
ACCESS 
FULL
| T2   |11 |   110 | 3   (0)| 00:00:01 |
|   5 |    
TABLE 
ACCESS 
FULL
| T3   |21 |   210 | 3   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
   
1 - access(
"T1"
.
"OBJECT_TYPE"
=
"T3"
.
"OBJECT_TYPE"
)
   
3 - access(
"T2"
.
"OBJECT_ID"
=
"T3"
.
"OBJECT_ID"
)

转:http://7642644.blog.51cto.com/7632644/1699902

转载于:https://www.cnblogs.com/andy6/p/6790184.html

你可能感兴趣的文章
red5安装时候出现服务不能启动异常
查看>>
查找目录下的所有文件中是否含有某个字符串
查看>>
段错误以及调试方式
查看>>
javascript中的时间处理
查看>>
JS正则截取两个字符串之间的字符串
查看>>
从零开始学习OpenCL开发(三)深入API
查看>>
新时期读书的价值
查看>>
hdoj 1226 超级password 【隐图BFS】
查看>>
10年工作经验老程序员推荐的7个开发类工具
查看>>
C# sqlserver 2008 连接字符串
查看>>
相关列的基数计算
查看>>
Java阅读word程序说明文件
查看>>
JSpider是一个用Java实现的WebSpider
查看>>
cocos2dx-3.0(13)------SpriteBatchNode与SpriteFrameCache渲染速度
查看>>
oracle备份和升级数据库
查看>>
linux shell 正则表达式(BREs,EREs,PREs)差异比较
查看>>
数据库的读读事务也会产生死锁
查看>>
使用paramiko进行打包操作
查看>>
ubuntu下允许root用户ssh远程登录
查看>>
Asp.Net Mvc: 浅析TempData机制
查看>>