SWAP_JOIN_INPUTS Oracle Hint(处理hash join强制大表(segment_size大)作为被驱动表)

简介:

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

文章可以转载,必须以链接形式标明出处。


本文转自 张冲andy 博客园博客,原文链接:  http://www.cnblogs.com/andy6/p/6790184.html  ,如需转载请自行联系原作者
相关文章
|
8月前
|
Oracle 关系型数据库 Java
实时计算 Flink版操作报错之读取Oracle数据库时遇到找不到驱动,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
实时计算 Flink版操作报错之读取Oracle数据库时遇到找不到驱动,是什么原因
|
8月前
|
SQL Oracle 关系型数据库
避坑,Oracle中left join 与 (+) 的区别
避坑,Oracle中left join 与 (+) 的区别
|
存储 SQL Oracle
Oracle数据库批量删除表、视图、序列、存储过程、函数脚本
Oracle数据库批量删除表、视图、序列、存储过程、函数脚本
143 0
|
8月前
|
Oracle 关系型数据库 数据库
Oracle查询优化-复制表的定义及数据
【1月更文挑战第5天】【1月更文挑战第14篇】在Oracle数据库中,复制表定义和复制表数据是两个常见的操作。
115 1
|
SQL Oracle 关系型数据库
解决:Oracle数据库中Left join on 后面为null时匹配不上
解决:Oracle数据库中Left join on 后面为null时匹配不上
325 0
|
8月前
|
消息中间件 关系型数据库 Kafka
实时计算 Flink版产品使用合集之oracle cdc 抽取新增一张表 可以从savepoint恢复吗
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6月前
|
Oracle 关系型数据库 Linux
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
通过这一连串的步骤,可以专业且有效地在Linux下为Qt编译Oracle驱动库 `libqsqloci.so`,使得Qt应用能够通过OCI与Oracle数据库进行交互。这些步骤适用于具备一定Linux和Qt经验的开发者,并且能够为需要使用Qt开发数据库应用的专业人士提供指导。
187 1
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
|
6月前
|
SQL Oracle 关系型数据库
|
7月前
|
SQL Oracle 关系型数据库
实时计算 Flink版产品使用问题之oracle无主键的表支持同步吗如何实现
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
7月前
|
运维 DataWorks Oracle
DataWorks产品使用合集之在标准模式下,当同步Oracle的表或视图时,是否需要在源端的测试和生产环境中都存在要同步的表或视图
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
56 3

推荐镜像

更多