Dav_笔记14:优化程序提示 HINTs -2

发布于:2025-02-14 ⋅ 阅读:(15) ⋅ 点赞:(0)

优化方法和目标的提示

ALL_ROWS和FIRST_ROWS(n)提示允许您在优化方法和目标之间进行选择。如果SQL语句具有指定优化方法和目标的提示,则优化程序将使用指定的方法,无论是否存在统计信息,OPTIMIZER_MODE初始化参数的值以及ALTER SESSION语句的OPTIMIZER_MODE参数。

如果在SQL语句中指定ALL_ROWS或FIRST_ROWS(n)提示,并且数据字典没有关于语句访问的表的统计信息,

注意:

优化程序目标仅适用于直接提交的查询。 使用提示指定从PL / SQL中提交的任何SQL语句的访问路径。 ALTER SESSION ... SET OPTIMIZER_MODE语句不影响PL / SQL中的SQL运行。

然后,优化器使用默认统计值(例如此类表的已分配存储)来估计缺少的统计信息并选择执行计划。 这些估计可能不如DBMS_STATS包收集的那些准确,因此使用DBMS_STATS来收集统计信息。

如果为访问路径或连接操作指定提示以及ALL_ROWS或FIRST_ROWS(n)提示,则优化程序优先考虑提示指定的访问路径和连接操作。

启用优化程序功能的提示

OPTIMIZER_FEATURES_ENABLE提示充当伞形参数,用于基于Oracle数据库版本号启用一系列优化程序功能。 此提示是在数据库升级后检查计划回归的有用方法。

指定版本号作为提示的参数。 以下示例使用Oracle Database 11g第1版(11.1.0.6)中的优化程序功能运行查询:

SELECT /*+ optimizer_features_enable('11.1.0.6') */ employee_id, last_name

FROM employees

ORDER BY employee_id;

访问路径的提示

以下提示指示优化器使用表的特定访问路径:

■FULL

■cluster

■HASH

■INDEX和NO_INDEX

■INDEX_ASC和INDEX_DESC

■INDEX_COMBINE和INDEX_JOIN

■INDEX_JOIN

■INDEX_FFS和NO_INDEX_FFS

■INDEX_SS和NO_INDEX_SS

■INDEX_SS_ASC和INDEX_SS_DESC

指定前面提示之一会导致优化器仅在访问路径基于索引或集群的存在以及SQL语句的语法结构可用时才选择指定的访问路径。 如果提示指定了不可用的访问路径,则优化程序会忽略它。

您必须完全按照语句中显示的方式指定要访问的表。 如果语句使用表的别名,则使用别名而不是提示中的表名。 如果语句中存在模式名称,则提示中的表名称不应包含模式名称。

Hints for Join Orders

以下提示建议加入顺序:

■LEADING

■ORDERED

加入操作的提示

以下提示指示优化器对表使用特定的连接操作:

■USE_NL和NO_USE_NL

■USE_NL_WITH_INDEX

■USE_MERGE和NO_USE_MERGE

■USE_HASH和NO_USE_HASH

■NO_USE_HASH

对于任何连接顺序提示,建议使用USE_NL和USE_MERGE提示。请参阅“加入订单提示”。当引用的表被强制为连接的内部表时,Oracle数据库使用这些提示;如果引用的表是外部表,则忽略提示。

有关可合并视图的提示行为,请参阅“访问路径和视图上的联接提示”和“访问路径和视图内的联接提示”。

在线应用程序升级的提示

在线应用程序升级提示建议在使用基于版本的重新定义执行在线应用程序升级时如何处理冲突的INSERT和UPDATE操作:

■CHANGE_DUPKEY_ERROR_INDEX

■IGNORE_ROW_ON_DUPKEY_INDEX

■RETRY_ON_ROW_CHANGE

您可以使用CHANGE_DUPKEY_ERROR_INDEX和IGNORE_ROW_ON_DUPKEY_INDEX提示来处理在线应用程序升级期间冲突的INSERT操作。您可以使用CHANGE_DUPKEY_ERROR_INDEX提示来标识指定的一组列或索引的唯一键冲突。在INSERT或UPDATE操作期间遇到唯一键冲突时,会报告ORA-38911错误而不是ORA-001。您可以使用IGNORE_ROW_ON_DUPKEY_INDEX提示忽略指定的一组列或索引的唯一键冲突。在单表INSERT操作期间遇到唯一键冲突时,将发生行级回滚,并继续执行下一个输入行。因此,唯一键冲突不会导致INSERT终止或报告错误。

您可以使用RETRY_ON_ROW_CHANGE提示在联机应用程序升级期间处理冲突的UPDATE操作。如果一个或多个行从确定要修改的行集的时间更改为实际修改行集的时间,则可以使用此提示重试UPDATE或DELETE操作。

并行执行的提示

并行执行提示指示优化器是否以及如何并行化操作。您可以使用以下并行提示:

■PARALLEL和NO_PARALLEL

■PARALLEL_INDEX和NO_PARALLEL_INDEX

■PQ_DISTRIBUTE

以下部分将提示分组为功能类别。

控制并行度的提示

以关键字PARALLEL开头的提示表示查询的并行度。以NO_PARALLEL开头的提示禁用并行性。

您可以在语句或对象级别指定并行度。如果未在提示中显式指定对象,则会在语句级别发生并行性。与大多数提示相反,并行语句级提示优先于对象级提示。

为了说明对象级和语句级并行设置之间的区别,假设您执行以下步骤:

1.您将employees表上的并行度设置设置为2,并在departments表上禁用并行性,如下所示:

ALTER TABLE employees PARALLEL 2;

ALTER TABLE departments NOPARALLEL;

2.您执行以下SELECT语句:

SELECT /*+ PARALLEL(employees 3) */ e.last_name, d.department_name

FROM employees e, departments d

WHERE e.department_id=d.department_id;

员工的PARALLEL提示将覆盖步骤1中指定的此表的并行度2。

在例19-1的解释计划中,IN-OUT列显示了用于员工并行访问的PCWP和用于部门串行访问的S. 由于在步骤1中将NOPARALLEL设置应用于此表,因此序列化了对部门的访问。

3.您执行以下SELECT语句:

SELECT /*+ PARALLEL(4) */ hr_emp.last_name, d.department_name

FROM employees hr_emp, departments d

WHERE hr_emp.department_id=d.department_id;

由于PARALLEL提示中未指定任何架构对象,因此提示的范围是语句,而不是对象。此语句强制查询employees和departments表,执行的并行度为4,从而覆盖表上定义的并行度设置。

提示控制连接的分配方法

PQ_DISTRIBUTE提示控制指定连接操作的分发方法。基本语法如下,其中distribution是在生成器和连接的左侧和右侧的使用者从属之间使用的分发方法:

/ * + PQ_DISTRIBUTE(tablespec,distribution)* /

例如,在HASH,HASH分发中,使用连接键上的散列函数将每个表的行映射到消费者查询服务器。映射完成后,每个查询服务器都会在一对结果分区之间执行连接。当表的大小相当并且通过散列连接或排序合并连接实现连接操作时,建议使用此分发。以下查询包含使用哈希分布的提示:

SELECT /*+ORDERED PQ_DISTRIBUTE(departments HASH, HASH) USE_HASH (departments)*/

e.employee_id, d.department_name

FROM employees e, departments d

WHERE e.department_id=d.department_id;

控制负载分配方法的提示

PQ_DISTRIBUTE提示适用于并行INSERT ... SELECT和并行CREATE TABLE AS SELECT语句,以指定应如何在生产者(查询)和使用者(加载)从属之间分配行。

例如,PARTITION分布使用正在加载的表的分区信息将行从查询从属分发到负载从属。 满足以下条件时使用此方法:

■无法或不希望将查询和加载操作组合到每个从站中。

■正在加载的分区数大于或等于负载从站数。

■输入数据均匀分布在正在加载的分区上。

以下示例语句创建一个表并指定PARTITION分配方法:

CREATE /*+ PQ_DISTRIBUTE(lineitem, PARTITION) */ TABLE lineitem

NOLOGGING PARALLEL 16

PARTITION BY HASH (l_orderkey) PARTITIONS 512

AS SELECT * FROM lineitemxt;

相反,NONE分布将查询和加载操作组合到每个从属中。 因此,所有从站都加载所有分区。 使用此分布可避免在没有倾斜时分配行的开销。 以下示例SQL语句指定插入到lineitem表中的NONE分布:

INSERT /*+ APPEND PARALLEL(LINEITEM, 16) PQ_DISTRIBUTE(LINEITEM, NONE) */

INTO lineitem

(SELECT * FROM lineitemxt);

后面有时间继续写....