Oracle SQL 性能调优:使用Hint固定执行计划1(Hash Join)
2023-06-13 09:11:16 时间
编者按:
本文作者系杨昱明,现就职于甲骨文公司,从事数据库方面的技术支持。希望能通过发表文章,把一些零散的知识再整理整理。个人主页:https://blog.csdn.net/weixin_50513167,经其本人授权发布。
Hash Join 是不使用索引等价结合时,最有效的结合方式,所以,使用的机会非常之多。
Hash Join 是在内存中作出 Hash Table 用来存放结合数据。通常,会先访问数据量少的表,之后再访问数据量多的表,这样能保证性能。
先访问的表叫做 Build表,第二个访问的表叫做 Probe表。那么假如 3个以上的表进行 Hash Join 时,各表之间的结合顺序,以及那个表作为 Build表,那个表作为 Probe表,如何来控制呢。
下面我们介绍一下相关的 Hint 来进行有效的控制。
LEADING Hint (指定 Hash Join 顺序)
SWAP_JOIN_INPUTS Hint(指定 Build 表)
NO_SWAP_JOIN_INPUTS Hint(指定 Probe 表)
USE_HASH (指定使用 Hash Join)
下面用几个例子来做一下展示。
准备:
drop table t1 purge;
drop table t2 purge;
drop table t3 purge;
create table t1(c1 number, c2 number);
create table t2(c1 number, c2 number);
create table t3(c1 number, c2 number);
insert into t1 values (1,1);
insert into t2 values (1,2);
insert into t3 values (1,3);
commit;
Case 1:
结合顺序是 A->B(Build 表)->C
SQL> select /*+ leading(a b c) use_hash(b c) swap_join_inputs(b) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;
C1 C2 C1 C2 C1 C2
---------- ---------- ---------- ---------- ---------- ----------
1 1 1 2 1 3
Execution Plan
----------------------------------------------------------
Plan hash value: 1184213596
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 78 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 78 | 9 (0)| 00:00:01 |
|* 2 | HASH JOIN | | 1 | 52 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 1 | 26 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| T1 | 1 | 26 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | T3 | 1 | 26 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."C1"="C"."C1")
2 - access("A"."C1"="B"."C1")
Case 2:
结合顺序是 A->B(Build表)->C(Build表)
SQL> select /*+ leading(a b c) swap_join_inputs(b) swap_join_inputs(c) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;
C1 C2 C1 C2 C1 C2
---------- ---------- ---------- ---------- ---------- ----------
1 1 1 2 1 3
Execution Plan
----------------------------------------------------------
Plan hash value: 1487401159
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 78 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 78 | 9 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | T3 | 1 | 26 | 3 (0)| 00:00:01 |
|* 3 | HASH JOIN | | 1 | 52 | 6 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| T2 | 1 | 26 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL| T1 | 1 | 26 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."C1"="C"."C1")
3 - access("A"."C1"="B"."C1")
Case 3:
结合顺序是 A->C(Build表)->B
SQL> select /*+ leading(a c b) USE_HASH(c b) swap_join_inputs(c) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;
C1 C2 C1 C2 C1 C2
---------- ---------- ---------- ---------- ---------- ----------
1 1 1 2 1 3
Execution Plan
----------------------------------------------------------
Plan hash value: 2467348796
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 78 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 78 | 9 (0)| 00:00:01 |
|* 2 | HASH JOIN | | 1 | 52 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T3 | 1 | 26 | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| T1 | 1 | 26 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | T2 | 1 | 26 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."C1"="B"."C1")
2 - access("A"."C1"="C"."C1")
另外,以上面的例子来说,可以用 C->B->A 的顺序进行 Hash Join 吗。不可以哈,因为 B表和 C表之间没有结合键,这样会产生笛卡尔积。
SQL> select /*+ leading(c b a) USE_HASH(c b) */ * from t1 a, t2 b, t3 c where a.c1=b.c1 and a.c1=c.c1;
C1 C2 C1 C2 C1 C2
---------- ---------- ---------- ---------- ---------- ----------
1 1 1 2 1 3
Execution Plan
----------------------------------------------------------
Plan hash value: 2210115829
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 78 | 9 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 78 | 9 (0)| 00:00:01 |
| 2 | MERGE JOIN CARTESIAN| | 1 | 52 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | T3 | 1 | 26 | 3 (0)| 00:00:01 |
| 4 | BUFFER SORT | | 1 | 26 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | T2 | 1 | 26 | 3 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | T1 | 1 | 26 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("A"."C1"="B"."C1" AND "A"."C1"="C"."C1")
————————————————
相关文章
- Oracle设置变量 打造效率无限(oracle设置变量)
- 从Oracle中取出分组最大值(oracle分组取最大值)
- Oracle连接池:优化程序性能的利器(oracle连接池c)
- 提升Oracle性能:修改块大小(oracle修改块大小)
- 创建Oracle用户:使用SQL语句(oracle创建用户语句)
- Oracle序列设置缓存值优化性能(oracle序列缓存)
- 掌握Oracle触发器类型,实现数据精准控制(oracle触发器类型)
- 成为Oracle认证专家,开启职业世界新旅程(oracle认证专家)
- OracleSSMA:快速实现SQL Server和Oracle数据库的集成(oracle ssma)
- Oracle表增加分区:简单提升数据库性能(oracle表增加分区)
- 更新Oracle版本更新新功能与性能大幅提升(oracle 关于版本)
- C程序运行Oracle SQL语句的实现(c 执行oracle语句)
- 数据库的优化EF框架提升Oracle数据库性能的利器(ef框架对oracle)
- Oracle DTT 技术用于优化数据库性能(dtt oracle)
- 优化Oracle数据库性能主键和索引的结合使用(oracle 主键加索引)
- Oracle中掌控用户权限的正确之路(oracle中的用户权限)
- Oracle优化用正确顺序实现性能最大化(oracle优化顺序)
- 使用Oracle存储大量数据的简单方法(oracle中的大字段)
- select在Oracle中使用TOP Select语句(oracle中有top)
- Oracle数据库性能优化获得业务锁表利益(oracle业务锁表)
- 报表Oracle禁止生成AWR报表(oracle不生成awr)
- ,一库完成Oracle实现一库搞定,无需再分库(oracle 不分库)
- Oracle SQL不容忽视的不为空判断(oracle不为空sql)
- Oracle两行之差实现轻松精确(oracle上下两行相减)
- 间空间技术提升 Oracle SQL 性能(oracle sql 空)