一、与优化器模式相关的Hint
1、ALL_ROWS
ALL_ROWS是针对整个目标SQL的Hint,它的含义是让优化器启用CBO,而且在得到目标SQL的执行计划时会选择那些吞吐量最佳的执行路径。这里的“吞吐量最佳”是指资源消耗量(即对I/O、CPU等硬件资源的消耗量)最小,也就是说在ALL_ROWS Hint生效的情况下,优化器会启用CBO而且会依据各个执行路径的资源消耗量来计算它们各自的成本。
ALL_ROWS Hint的格式如下:
/*+ ALL_ROWS */
使用范例:
select /*+ all_rows */ empno,ename,sal,job
from emp
where empno=7396;
从Oracle10g开始,ALL_ROWS就是默认的优化器模式,启用的就是CBO。
scott@TEST>show parameter optimizer_mode
NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
optimizer_mode string ALL_ROWS
如果目标SQL中除了ALL_ROWS之外还使用了其他与执行路径、表连接相关的Hint,优化器会优先考虑ALL_ROWS。
2、FIRST_ROWS(n)
FIRST_ROWS(n)是针对整个目标SQL的Hint,它的含义是让优化器启用CBO模式,而且在得到目标SQL的执行计划时会选择那些能以最快的响应时间返回头n条记录的执行路径,也就是说在FIRST_ROWS(n) Hint生效的情况下,优化器会启用CBO,而且会依据返回头n条记录的响应时间来决定目标SQL的执行计划。
FIRST_ROWS(n)格式如下:
/*+ FIRST_ROWS(n) */
使用范例
select /*+ first_rows(10) */ empno,ename,sal,job
from emp
where deptno=30;
上述SQL中使用了/*+ first_rows(10) */,其含义是告诉优化器我们想以最短的响应时间返回满足条件"deptno=30"的前10条记录。
注意,FIRST_ROWS(n) Hint和优化器模式FIRST_ROWS_n不是一一对应的。优化器模式FIRST_ROWS_n中的n只能是1、10、100、1000。但FIRST_ROWS(n) Hint中的n还可以是其他值。
scott@TEST>alter session set optimizer_mode=first_rows_9;
ERROR:
ORA-00096: invalid value FIRST_ROWS_9 for parameter optimizer_mode, must be from among first_rows_1000, first_rows_100, first_rows_10, first_rows_1, first_rows, all_rows, choose,rule
scott@TEST>set autotrace traceonly
scott@TEST>select /*+ first_rows(9) */ empno from emp;
14 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 179099197
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 36 | 1 (0)| 00:00:01 |
| 1 | INDEX FULL SCAN | PK_EMP | 9 | 36 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
如果在UPDATE、DELETE或者含如下内容的查询语句中使用了FIRST_ROWS(n) Hint,则该Hint会被忽略:
集合运算(如UNION,INTERSACT,MINUS,UNION ALL等)
GROUP BY
FOR UPDATE
聚合函数(比如SUM等)
DISTINCT
ORDER BY(对应的排序列上没有索引)
这里优化器会忽略FIRST_ROWS(n) Hint是因为对于上述类型的SQL而言,Oracle必须访问所有的行记录后才能返回满足条件的头n行记录,即在上述情况下,使用该Hint是没有意义的。
3、RULE
RULE是针对整个目标SQL的Hint,它表示对目标SQL启用RBO。
格式如下:
/*+ RULE */
使用范例:
select /*+ rule */ empno,ename,sal,job
from emp
where deptno=30;
RULE不能与除DRIVING_SITE以外的Hint联用,当RULE与除DRIVING_SITE以外的Hint联用时,其他Hint可能会失效;当RULE与DRIVING_SITE联用时,它自身可能会失效,所以RULE Hint最好是单独使用。
一般情况下,并不推荐使用RULE Hint。一来是因为Oracle早就不支持RBO了,二来启用RBO后优化器在执行目标SQL时可选择的执行路径将大大减少,很多执行路径RBO根本就不支持(比如哈希连接),就也就意味着启用RBO后目标SQL跑出正确执行计划的概率将大大降低。
因为很多执行路径RBO根本就不支持,所以即使在目标SQL中使用了RULE Hint,如果出现了如下这些情况(包括但不限于),RULE Hint依然会被Oracle忽略。
目标SQL除RULE之外还联合使用了其他Hint(如DRIVING_SITE)。
目标SQL使用了并行执行
目标S