oracle hints

本文介绍了 Oracle SQL 中 hint 的使用方法,特别是 use_hash 和 leading/ordered hint 的区别及应用场景。通过实例展示了如何指定连接方式及驱动表,帮助读者更好地理解和优化查询计划。

oracle hints

    今天是2013-10-08,对于oracle hint有很多,具体可以参考联机手册:

http://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements006.htm#BABIJGJF

http://docs.oracle.com/cd/E11882_01/server.112/e41573/hintsref.htm#PFGRF501

刚刚开始,我进行hash join连接发现如下:

SQL> select /*+use_hash(emp)*/ empno from emp,dept where dept.deptno=emp.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 716400937

-----------------------------------------------------------------------------------
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |               |    14 |   140 |     1   (0)| 00:00:01 |
|   1 |  NESTED LOOPS     |               |    14 |   140 |     1   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN | IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN| REVERSE_INDEX |     1 |     3 |     0   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

SQL> 


我明明指定的是emp做为驱动表然后进行hash join,但是不行,需要指定另个表,但是use_hash不能规定优化器来选择驱动表。

eg:

SQL> select /*+use_hash(emp,dept)*/ empno from emp,dept where dept.deptno=emp.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 2255485930

----------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    14 |   140 |     2   (0)| 00:00:01 |
|*  1 |  HASH JOIN       |               |    14 |   140 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| REVERSE_INDEX |     4 |    12 |     1   (0)| 00:00:01 |
|   3 |   INDEX FULL SCAN| IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

SQL> select /*+use_hash(dept,emp)*/ empno from dept,emp where dept.deptno=emp.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 2255485930

----------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    14 |   140 |     2   (0)| 00:00:01 |
|*  1 |  HASH JOIN       |               |    14 |   140 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| REVERSE_INDEX |     4 |    12 |     1   (0)| 00:00:01 |
|   3 |   INDEX FULL SCAN| IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

SQL> 


我们可以选择使用ordered或是leading来指定optimizer选择哪个表为驱动表。

note:

The LEADING hint instructs the optimizer to use the specified set of tables as the prefix in the execution plan. This hint is more versatile than the ORDERED hint.

The LEADING hint is ignored if the tables specified cannot be joined first in the order specified because of dependencies in the join graph. If you specify two or more conflicting LEADING hints, then all of them are ignored. If you specify the ORDERED hint, it overrides all LEADING hints.

 

The ORDERED hint instructs Oracle to join tables in the order in which they appear in the FROM clause. Oracle recommends that you use the LEADING hint, which is more versatile than the ORDERED hint.

When you omit the ORDERED hint from a SQL statement requiring a join, the optimizer chooses the order in which to join the tables. You might want to use the ORDERED hint to specify a join order if you know something that the optimizer does not know about the number of rows selected from each table. Such information lets you choose an inner and outer table better than the optimizer could.

eg:

SQL> select /*+leading(emp) use_hash(dept,emp)*/ empno from dept ,emp where dept.deptno=emp.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 929644576

----------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    14 |   140 |     2   (0)| 00:00:01 |
|*  1 |  HASH JOIN       |               |    14 |   140 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
|   3 |   INDEX FULL SCAN| REVERSE_INDEX |     4 |    12 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

SQL> select /*+leading(dept) use_hash(dept,emp)*/ empno from dept ,emp where dept.deptno=emp.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 2255485930

----------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    14 |   140 |     2   (0)| 00:00:01 |
|*  1 |  HASH JOIN       |               |    14 |   140 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| REVERSE_INDEX |     4 |    12 |     1   (0)| 00:00:01 |
|   3 |   INDEX FULL SCAN| IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("DEPT"."DEPTNO"="EMP"."DEPTNO")

SQL> 


 

SQL> select /*+ordered use_hash(emp,dept)*/ empno from emp,dept where emp.deptno=dept.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 929644576

----------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    14 |   140 |     2   (0)| 00:00:01 |
|*  1 |  HASH JOIN       |               |    14 |   140 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
|   3 |   INDEX FULL SCAN| REVERSE_INDEX |     4 |    12 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

SQL> select /*+ordered use_hash(emp,dept)*/ empno from dept,emp  where emp.deptno=dept.deptno;

Execution Plan
----------------------------------------------------------
Plan hash value: 2255485930

----------------------------------------------------------------------------------
| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |               |    14 |   140 |     2   (0)| 00:00:01 |
|*  1 |  HASH JOIN       |               |    14 |   140 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| REVERSE_INDEX |     4 |    12 |     1   (0)| 00:00:01 |
|   3 |   INDEX FULL SCAN| IND_EMP       |    14 |    98 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

SQL> 


 

### Oracle 数据库 Hints 的用法与示例 Hints 是一种用于指导优化器如何处理 SQL 查询的技术。通过在查询中嵌入特定的提示,可以影响执行计划的选择,从而提高性能或解决问题。 #### 1. 基本概念 Hints 提供了一种机制来覆盖默认的优化器行为。它们通常以 `/*+ hint_name */` 的形式出现在 SQL 语句中[^1]。这些提示可以帮助开发者指定索引、连接方法或其他执行策略。 #### 2. 使用场景 以下是几种常见的 Hints 及其用途: - **INDEX Hint**: 强制优化器使用某个特定的索引来访问数据表。例如: ```sql SELECT /*+ INDEX(employees emp_last_name_idx) */ employee_id, last_name FROM employees WHERE last_name = 'Smith'; ``` 这里指定了名为 `emp_last_name_idx` 的索引被用来加速查询操作[^1]。 - **FULL Table Scan Hint**: 如果希望绕过索引而直接进行全表扫描,则可采用 FULL 提示: ```sql SELECT /*+ FULL(departments) */ department_id, department_name FROM departments; ``` - **PARALLEL Execution Hint**: 对于大规模的数据集,启用并行处理可能显著提升效率。注意,在 RAC 环境下,并行度由整个集群范围内的资源决定[^2]: ```sql SELECT /*+ PARALLEL(employees, 8) */ COUNT(*) FROM employees e JOIN departments d ON (e.department_id = d.department_id); ``` - **NO_PARALLEL Hint**: 当不期望某条查询触发并行化时,可以通过 NO_PARALLEL 来禁用它: ```sql SELECT /*+ NO_PARALLEL(employees) */ * FROM employees; ``` - **DRIVING_SITE Hint**: 在分布式环境中控制哪个站点驱动查询可能是必要的。比如让远程服务器主导计算过程: ```sql SELECT /*+ DRIVING_SITE(remote_table@dblink) */ col1, col2 FROM local_table l, remote_table@dblink r WHERE l.id = r.ref_id; ``` #### 3. 调试与验证 为了确认所加的 Hints 是否生效以及实际产生的执行计划是什么样的,应该利用如下工具查看最终的结果[^4]: ```sql SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST')); ``` 此命令能够展示最近运行过的游标的详细解释信息,包括任何因适应性调整而导致的变化情况。 #### 4. 版本兼容性和支持状况 值得注意的是并非所有的版本都完全一致地实现了同样的功能集合;特别是较新的特性往往只存在于更新版的产品线当中[^3]。因此,在应用之前务必核查当前使用的数据库软件是否满足最低需求标准。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值