热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:SWAP_JOIN_INPUTSOracleHint(处理hashjoin强制大表(segment_size大)作为被驱动表)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了SWAP_JOIN_INPUTSOracleHint(处理hashjoin强制大表(segment_size大)作为被驱动表)相关的知识,

篇首语:本文由编程笔记#小编为大家整理,主要介绍了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



[email&#160;protected]> create table t1 as select from dba_objects where rownum<2;

Table created.

[email&#160;protected]> create table t2 as select from dba_objects where rownum<12;

Table created.

[email&#160;protected]> create table t3 as select from dba_objects where rownum<22;

Table created.




收集统计信息:












1

2

3

4

5

6



[email&#160;protected]> 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.

[email&#160;protected]> 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.

[email&#160;protected]> 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



[email&#160;protected]> select count(*) from t1;

 COUNT(*)

-----------------

1

1 row selected.

[email&#160;protected]> select count(*) from t2;

 COUNT(*)

-----------------

       11

1 row selected.

[email&#160;protected]> 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



推荐阅读
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 本文介绍了Java集合库的使用方法,包括如何方便地重复使用集合以及下溯造型的应用。通过使用集合库,可以方便地取用各种集合,并将其插入到自己的程序中。为了使集合能够重复使用,Java提供了一种通用类型,即Object类型。通过添加指向集合的对象句柄,可以实现对集合的重复使用。然而,由于集合只能容纳Object类型,当向集合中添加对象句柄时,会丢失其身份或标识信息。为了恢复其本来面貌,可以使用下溯造型。本文还介绍了Java 1.2集合库的特点和优势。 ... [详细]
author-avatar
用户cnhr0qjy0s
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有