查询转换的提示
以下每个提示都指示优化程序使用特定的SQL查询转换:
■NO_QUERY_TRANSFORMATION
■USE_CONCAT
■NO_EXPAND
■REWRITE和NO_REWRITE
■MERGE和NO_MERGE
■STAR_TRANSFORMATION和NO_STAR_TRANSFORMATION
■事实和NO_FACT
■UNNEST和NO_UNNEST
附加提示
以下是几个额外的提示:
■APPEND,APPEND_VALUES和NOAPPEND
■CACHE和NOCACHE
■PUSH_PRED和NO_PUSH_PRED
■PUSH_SUBQ和NO_PUSH_SUBQ
■QB_NAME
■CURSOR_SHARING_EXACT
■DRIVING_SITE
■动态采样
■MODEL_MIN_ANALYSIS
指定提示
提示仅适用于它们出现的语句块的优化。语句块是以下任何一个语句或语句的一部分:
■简单的SELECT,UPDATE或DELETE语句
■复杂语句的父语句或子查询
■复合查询的一部分
例如,由UNION运算符组合的两个组件查询组成的复合查询有两个块,每个块用于一个组件查询。因此,第一个组件查询中的提示仅适用于其优化,而不适用于第二个组件查询的优化。
以下部分更详细地讨论了提示的使用。
指定一整套提示
使用提示时,在某些情况下,您可能需要指定一整套提示以确保最佳执行计划。 例如,如果您有一个非常复杂的查询(包含许多表连接),并且如果仅指定给定表的INDEX提示,则优化程序必须确定要使用的剩余访问路径以及相应的连接方法。 因此,即使您提供了INDEX提示,优化程序也可能不一定使用该提示,因为优化程序可能已确定由于优化程序选择的连接方法和访问路径而无法使用所请求的索引。
在例2中,LEADING提示指定了精确的连接顺序。 还指定了连接方法。
示例2指定一组完整的提示
SELECT /*+ LEADING(e2 e1) USE_NL(e1) INDEX(e1 emp_emp_id_pk)
USE_MERGE(j) FULL(j) */
e1.first_name, e1.last_name, j.job_id, sum(e2.salary) total_sal
FROM employees e1, employees e2, job_history j
WHERE e1.employee_id = e2.manager_id
AND e1.employee_id = j.employee_id
AND e1.hire_date = j.start_date
GROUP BY e1.first_name, e1.last_name, j.job_id
ORDER BY total_sal;
在提示中指定查询块
要在查询中标识查询块,可以在提示中使用可选的查询块名称来指定提示适用的块。查询块参数的语法格式为@queryblock,其中queryblock是指定查询中的块的标识符。查询块标识符可以是系统生成的,也可以是用户指定的。
请注意以下准则:
■您可以使用EXPLAIN PLAN获取系统生成的标识符以进行查询。您可以通过使用NO_QUERY_TRANSFORMATION提示运行EXPLAIN PLAN来查询预转换查询块名称。
■您可以使用QB_NAME提示设置用户指定的名称。
假设
本笔记假定以下内容:
■您打算创建包含嵌套查询块的employees和job_history的联接视图。
■您希望查询视图中的所有行,但仅将NO_UNNEST提示应用于查询块。
要将NO_UNNEST提示应用于查询块:
1.启动SQL * Plus并以用户hr身份登录。
2.创建视图。
例如,运行以下语句:
CREATE OR REPLACE VIEW v_emp_job_history AS
SELECT e1.first_name, e1.last_name, j.job_id, sum(e2.salary) total_sal
FROM employees e1, (SELECT * FROM employees e3) e2, job_history j
WHERE e1.employee_id = e2.manager_id
AND e1.employee_id = j.employee_id
AND e1.hire_date = j.start_date
AND e1.salary = ( SELECT max(e2.salary)
FROM employees e2
WHERE e2.department_id = e1.department_id )
GROUP BY e1.first_name, e1.last_name, j.job_id
ORDER BY total_sal;
3.解释查询v_emp_job_history的计划。
例如,运行以下SQL语句:
EXPLAIN PLAN FOR SELECT * FROM v_emp_job_history;
4.Query the plan table.
For example, run the following SQL statement:
SELECT PLAN_TABLE_OUTPUT
FROM TABLE(DBMS_XPLAN.DISPLAY(NULL, NULL, 'ALL'));
The database displays the plan.
5.在查询计划输出中,获取与查询块关联的操作ID,然后使用该ID查找查询块名称。
例如,以下计划显示employees表的完整扫描发生在操作11中,该操作对应于查询块@ SEL $ 4:
6.使用NO_UNNEST提示查询视图。
例如,运行以下SQL语句以应用NO_UNNEST提示来查询块@ SEL $ 4(包括样本输出):
SQL> SELECT /*+ NO_UNNEST( @SEL$4 ) */ * FROM v_emp_job_history;