优化器

Oracle 的优化器(Optimizer)实际上是数据库环境的参数设置。可以在INITsid.ORA 文件内的

OPTIMZER_MODE=RULE 或OPTIMZER_MODE=COST 或OPTIMZER_MODE=CHOOSE 来

设置优化目标。用户也可以在会话和查询方式下更改优化器的默认操作模式。

如果OPTIMZER_MODE=RULE,则激活基于规则的优化器(RBO)。基于规则的优化器按照一

系列的语法规则来推测可能执行路径和比较可替换的执行路径。

如果OPTIMZER_MODE=COST,则激活基于成本的优化器(CBO)。它使用ANALYZE 语句来

生成数据库对象的统计数据。这些统计数据包括表的行数、平均长度及索引中不同的关键字

数等。基于这些统计数据,成本优化器可以计算出可获得的执行路径的成本。并选择具有最

小的成本执行路径。在CBO 模式下,需要经常运行ANALYZE 命令来确保数据的准确性。

如果OPTIMZER_MODE=CHOOSE,则在表被分析的情况下激活基于成本的优化器。但当一

个查询分析的表是未被ANALYZE 分析统计过的时侯,CBO 优化器就决定进行全表扫描操

作。所以为了减少可能的全表扫描,应该尽量避免使用OPTIMZER_MODE=CHOOSE 选项。

下面介绍在编程序中常用到的语句优化。

讨论SQL 处理技术、优化方法以及优化程序如何执行SQL 语句。包括:

 SQL 处理体系结构

 EXPLAIN PLAN

 优化程序的定义

 选择优化程序的方法和目标

 基于开销的优化程序(CBO=Cost_Base Optimizer)

 CBO 参数

 可扩展的优化程序

 基于规则的优花程序(RBO=Rule_Base Optimizer)

 优化程序操作概述

   优化连接(Join)

 优化使用公共子表达式的语句

 表达及条件的评价

 转换及优化的语句

SQL 处理体系结构主要有:

 解析程序

 优化程序

 行源产生程序

 SQL 执行

解析程序执行下面两种功能:

 语法分析:检查SQL 语句的语法正确性

 语义分析:例如检查当前数据库对象和相应的对象属性,并判断其准确性。

优化器是SQL 处理引擎的核心,Oracle 服务器支持两种优化方法:基于规则的优化和基

于开销的优化程序

行源程序产生器(Row Source generator)从优化程序接受优化规则,并输出SQL 语句的执

行规则。执行规则由行源的集合所组成,它呈现出树型结构。行源程序是一种迭代的控制结

构,它以迭代的方式对执行集合进行处理,并且每次只处理一次

SQL 执行(Execution)是操作执行规则时的组件,它与SQL 语句紧密相连,并且可以给出查

询的结果。

通过使用EXPLAIN PLAN 语句,用户可以对SQL 语句优化程序所选择的执行规划进行

检查。只要发出EXPLAIN PLAN 语句,就可以对输出表进行查询,下面是输出表的数据描述

先前所检查的语句:

ID   OPERATION                                 OPTION                     OBJECT_NAME

----- ----------------------------------------- ------------------------- -----------------------

0 SELECT STATEMENT

1 FILTER

2 NESTED LOOPS

3 TABLE ACCESS                                     FULL                         EMP

4 TABLE ACCESS                                     BY ROWID                DEPT

5 INDEX                                                  UNIQUNE SCAN        PK_DEPTNO

6 TABLE ACCESS                                     FULL                         SALGRADE

默认方式下,基于代价(CBO)是最好的方法。它使用最少的资源就能对所有行进行处

理。Oracle也可以使用时间响应来优化语句。如: SQL语句并行执行。优化器可以选择最小共

用资源消费开支时间。它可以由参数OPTIMIZER_PERCENT_PARALLEL来指定并行执行的优

化器的个数。

执行计划由优化器根据目标来产生。最大吞吐量优化类似于宁愿不要索引的全表扫描的结果

或者相当于不要嵌套循环的分类合并连接。然而最佳响应时间的优化有点类似于索引扫描或

嵌套循环连接。

例如你可以在任意的嵌套循环操作中或分类合并操作中使用连接语句。当嵌套循环操作快速

返回第一行时,这些分类合并语句也可以快速返回整个结果。如果你的目标是改善吞吐量。

那么优化器就有点象选择分类合并连接操作。如果你的目标是选择改善响应时间,则优化器

更象选择一个嵌套连接操作。

综合上面的描述,选择优化器主要是基 于应用的需要:

 对于批处理应用,如报表输出应用,需要采用吞吐量优化。因为吞吐量对于批处理来

说更重要。

 对于交互式应用,如Oracle Forms 应用或SQL*PLUS查询,需要采用最佳时间响应优

化。因为交互式用户等着看到第一行的数据。

 对于用ROWNUM来限制查询结果的查询,优化首先要考虑的响应时间。因为它要求

的是得到最快的结果。

当选择最佳路径和目标时,优化器受到下面因素的影响:

 ?OPTIMIZER_MODE 初始参数

 ?数据字典的统计数据

 ? ALTER SESSION 语句的OPTIMIZER_GOAL 参数

 ? 在提示中改变目标

OPTIMIZER_MODE 初始参数

可以用OPTIMIZER_MODE来建立优化路径的默认值,它可以取下面的值:

choose 表示优化器在基于代价和基于规则两种之间进行选择。如果数据字典有访问表的至少

一行的统计数据,则优化器使用的基于代价和最佳吞吐量方法。如果访问表没有统计数据,

则优化使用基于规则的路径。默认为基于规则的路径。

All_rows 对整个SQL语句,优化器使用基于代价的路径。使用最小资源返回整个行。

FIRST_ROWS 对整个SQL语句,优化器使用基于代价的路径。使用最小资源返回第一行。

RULE 对整个SQL语句,优化器使用基于规则的路径。

如果优化使用基于代价的路径,而访问的表没有统计数据时,优化器就使用该表的一些近似

值来代替。

数据字典中的统计数据

Oracle 为CBO 存储有列、表、簇 、索引及分区的统计数据。可以使用ANALYZE 语句或

COMPUTE STATISTICS 子句和DBMS_STATS 包来得到详细的统计结果。为了给优化提供最

新的数据,你应该经常使用ANALYZE 语句对表进行统计

ALTER SESSION 语句的OPTIMIZER_GOAL 参数

ALTER SESSION 语句中带OPTIMIZER_GOAL 参数可以越过初始化路径和

OPTIMIZER_MODE 参数所建立的目标。这个参数的结果影响到SQL 语句的优化。但它对会

话中所使用SQL 语句的递归不起作用。OPTIMIZER_GOAL 可以有下面的值:

choose 表示优化器在基于代价和基于规则两种之间进行选择。如果数据字典有访问表的至少

一行的统计数据,则优化器使用的基于代价和最佳吞吐量方法。如果访问表没有统计数据,

则优化使用基于规则的路径。默认为基于规则的路径。

All_rows 对整个SQL语句,优化器使用基于代价的路径。使用最小资源返回整个行。

FIRST_ROWS 对整个SQL语句,优化器使用基于代价的路径。使用最小资源返回第一行。

RULE 对整个SQL语句,优化器使用基于规则的路径。

关于提示的改变目标

可以在单个的SQL 语句中,使用FIRST_ROWS, ALL_ROWS, CHOOSE, 或 RULE 可以替代由

OPTIMIZER_MODE 初始参数和ALTER SESSION 的OPTIMIZER_GOAL 参数所设置的效果。

在默认下,系统使用的是基于最佳吞吐量的代价的优化。但可以用下面方法来改变CBO 的目

标:

 在会话中为CBO改变所有的SQL语句目标,使用:

ALTER SESSION SET OPTIMIZER_MODE 语句带 ALL_ROWS 或FIRST_ROWS子句。

 为单个SQL语句指定CBO的目标。使用 ALL_ROWS 或 FIRST_ROWS 提示。如:

ALTER SESSION SET OPTIMIZER_MODE = FIRST_ROWS;

基于代价优化器(CBO)

CBO在考虑访问路径和模式的统计数据(表或索引)来确定哪种执行计划最有效。同时CBO

也考虑提示语句中哪种是最优的建议。CBO 考虑下面步骤:

1. 优化器在它的有效路径和提示中为SQL语句产生一组潜在的计划。

2. 优化器根据数据字典的统计估计每个计划的代价,并存储表、索引和分区的特征。

代价(cost)是预期资源要求的估计值。优化器计算每一种访问方法的代价并基于估计计算机

资源(包括I/O和内存)的次序。从而得到执行该语句的需求。

较大的代价需要较多时间来执行,而较小的计划需要较少的时间来执行。当使用并行时,资

源不直接与消失的时间有关。

3. 优化器比较这些代价然后选择较小的代价。

维护CBO的有效性,必须收集有关的统计并使它们准确才行。可以用下面方法来收集统计数

据:

 用ANALYZE 语句;

 使用DBMS_STATS 包。

CBO 结构调整

CBO包括下面部件:

 查询转换器

 评价器

 规划产生程序

CBO 需求

要采用基于CBO的优化,要求下面的任何一种特征:

 分区的表

 索引构造的表

 逆键字索引

 基于函数的索引

   在SELECT语句中的SAMPLE子句

 并行执行和并行DML

 星形转换

 星形连接

 可执行的优化器

 查询重写(实体化视图)

 进展仪表(Progress meter)

 HASH 连接

 位图索引

使用CBO

要在语句中使用CBO,就要收集表的统计数据,并用下面方法来使CBO有效:

 确认OPTIMIZER_MODE 初始参数设置为 CHOOSE.

 在会话中启动CBO ,要用 ALTER SESSION SET OPTIMIZER_MODE 语句并带

ALL_ROWS 或FIRST_ROWS 子句。

 在一个单独的SQL语句中使用CBO,要用提示而不用RULE。

由CBO根据表的大小来产生规划,如果使用直方图情况下,还要产生的潜在的数据分布。当

通过具有少量数据的CBO来进行应用程序的原型测试时,不要认为实际数据库选择的规划与

原型数据库所选择的规划就一定一致。

CBO 访问路径

明确地描述执行计划如何从数据库返回数据是优化器的最重要选择之一。对于任何表的任意

行,该表的行的定位和返回都有许多的访问路径。优化器可从中选择一个。下面是Oracle访问

数据的基本方法:

全表扫描

全表扫描是从表中返回所有的行。执行全表扫描,Oracle从该表读所有的行。检查每一行,看

它是否满足where 子句的要求。实际上Oracle是读表中相继的数据块。所以它可以采用多块

读。

样本表扫描

Oracle在Oracle8i Release 8.1.6 版本之后,提供了在select 语句后加 SAMPLE BLOCK 来对表进

行部分的扫描查询。这种查询要求是只能对单表进行,不能在连接查询上使用样本扫描。也

不能在远程进行样本扫描。当然,如果希望在远程上进行样本扫描的话,可以先用CREATE

TABLE AS SELECT 语句将远程表复制到本地,然后在使用 SAMPLE BLOCK SAMPLE

BLOCK 语句。

例:扫描emp表的1%的内容,则发出:

select count(*)*100 from emp sample block(1);

SELECT * FROM emp SAMPLE BLOCK (1);

用Rowid访问表

用Oracle的rowid 也能访问到表的记录。每个行的rowid 能确定数据文件、行所在数据块及该行

所在的块位置。可以用rowid 来快速定位到一个单行。

簇(Cluster)扫描

对于以索引簇形式存放的表,簇扫描能够从中获得具有相同簇键(cluster key)值的行。在索引

化的簇中,所有具有相同簇键值的行都被存储进相同的数据库块中。为了执行簇扫描,Oracle

首先通过扫描簇的索引,并从 中得到所选择的rowid 值,然后再基于该rowid 对所有选择行进

行定位。

基于规则(RBO)的优化程序

尽管Oracle 支持基于RBO(Rule-Based Optimzer)的优化程序,但建议大多数系统还是采用

基于CBO 的优化。因为CBO 支持DSS 的某些新增强的功能,所以对于象数据仓库应用系统

也要采用CBO 方法。

如果满足:

1) 设置 OPTIMIZER_MODE=CHOOSE;

2) 数据字典中没有统计信息;

3) 未给SQL 语句加提示。

则可以采用RBO。

如果是:

1) OPTIMIZER_MODE=FIRST_ROWS 或ALL_ROWS ;

2) 不存在可用的统计信息;

则CBO 使用默认值

RBO 访问路径

如果使用基于RBO,则在执行规则中,访问路径的等级具有启发性,即如果存在多种可执行

的SQL 语句,则RBO 选择等级较低的操作,因为等级低的语句执行速度快。下面是RBO 访

问路径及等级:

 路径1:根据rowid 访问行

 路径2:通过cluster 联结访问行

 路径3:根据唯一性主键或主键的哈希簇访问单行

 路径4:根据唯一键或主键访问单行

 路径5:cluster 连接

 路径6:哈希cluster 键

 路径7:索引化cluster 键

 路径8:复合索引

 路径9:单列索引

 路径10:索引化有界搜索

 路径11:索引化无界搜索

 路径12:合并排序联结

 路径13:带有MAX 或MIN 的列

 路径14:带ORDER BY 的查询

 路径15:全表扫描

优化器操作

Oracle 接收到一条SQL 语句后,首先进行句法分析,检查文本并对该查询产生可执行的方案

(plan)。这个可执行的方案有EXPLAIN PLAN 来处理,方案确定后语句就被存放在SQL 共

享区内。而Oracle 的优化器是用来确当对特定语句的最佳执行路径。Oracle 的优化器可以有

两种类型:即基于规则和基于代价。下面是优化程序能进行优化的SQL 语句。

可优化的SQL 语句

 简单的SQL 语句,即只设计单个表的insert,update,select

 简单的查询

 等式连接

 非等式连接

 外连接

 笛卡尔乘积

 复合语句

 组合查询

 访问视图

 分布式语句

优化程序操作

优化程序自动简化SQL语句中的某些常用结构,如果结果简化执行的话,这些语句变

得非常简单,如2000/10 简化为 200 。也可能变复杂,如将带 OR 的运算语句转换为两个复

合的子查询。对于前者可以随时进行,但后者则取决于where 子句的列上是否有索引以及选

择哪种优化方法。

此外,还有一些其它的转换,包括:

 化简算术表达式

 将IN 转化为一系列的OR 条件

 将一个BETWEEN … AND 转换为一对比较表达式

 将 OR 转换为复合查询

 视图的定义合并到条件语句中

 将一个复杂语句转换成连接条件语句

基于规则或基于代价优化方法

Oracle 按照若干准则对每个语句进行优化,包括:

 引用的对象有一个并行度

 语句中的提示

 OPTIMZER_GOAL 的会话设置

 初始化参数OPTIMZER_MODE 的值

 被引用的对象的统计结果

通过优化程序的分析,决定执行是采用基于规则或基于代价方法。考察优化的首要因素是看

语句是否存在一次全表扫描和是否有并行(是否包括PARALLEL 选项)。如果都有的话,就

使用基于代价的优化来创建一个包含并行的执行计划。

基于规则的方法不支持并行处理语句的执行计划。如果没有rule 语句的提示,Oracle 都采用基

于代价方法进行优化

优化连接

Oracle 提供了4 种连接操作:

 嵌套循环连接(nested loop)

 合并排序连接(merge join)

 哈西连接(Hash join)

 簇连接(cluster join)

嵌套连接

嵌套循环连接(NESTED LOOPS)操作是将两个数据源连接起来。通常是在连接时系统提供

了可用的索引。实际在处理过程中,Oracle 先处理第1 行,接着下一行(不是等到整个处理完

毕才返回第1 行)。在处理嵌套连接时,Oracle 优化器首先为连接选择一个驱动表 ,可能对驱

动表进行全表扫描。对驱动表的每行进行索引检查,以便了解在表之间是否存在匹配。如果

有一个匹配存在,则通过NESTED LOOPS 操作并将该记录返回给用户。

例如:

SQL> explain plan for

select a.deptno,a.dname,b.empno,b.ename,b.sal

from dept a, emp b where a.deptno=b.deptno and a.deptno=20;

Explained.

SQL> select operation,options,object_name from plan_table;

OPERATION OPTIONS OBJECT_NAME

------------------ ------------------ ------------

SELECT STATEMENT

MERGE JOIN

TABLE ACCESS BY INDEX ROWID DEPT

INDEX UNIQUE SCAN PK_DEPT

FILTER

TABLE ACCESS FULL EMP

6 rows selected.

SQL> explain plan for

select a.deptno,a.dname,b.empno,b.ename,b.sal

from dept a, emp b where a.deptno=b.deptno and b.empno=7369;

Explained.

SQL> select operation,options,object_name from plan_table;

OPERATION OPTIONS OBJECT_NAME

------------------ ------------------ ------------

SELECT STATEMENT

NESTED LOOPS

TABLE ACCESS BY INDEX ROWID EMP

INDEX UNIQUE SCAN PK_EMP

TABLE ACCESS BY INDEX ROWID DEPT

INDEX UNIQUE SCAN PK_DEPT

6 rows selected.

在看为等价连接使用索引的例子:

SQL> select dept_id, id

2 from s_emp, s_dept

3 where s_emp.dept_id = s_dept.id;

这样Oracle 优化器使用嵌套循环连接替代排序合并连接。嵌套循环连接不需要任何的排序操

作,所以操作步骤为:

1 执行S_EMP 表全表扫描

2.每个返回行都使用DEPT_ID值,以在PK_ID索引上进行唯一扫描

3.使用从索引中返回的ROWID来定位S_DEPT表的相应行.

4. 为S_DEPT组合从S_EMP返回的每个行。

合并连接

排序合并连接用于从两个独立的数据源进行连接。HASH 连接可能执行比排序合并连接更好。

但另一方面,排序连接可能在下面情况下执行比HASH 连接更好。

 行源数据已经做过排序;

 一个排序也没有做。

然而,如果一个排序操作涉及到一个较慢的方法(如一个索引扫描对应全表扫描),则采用排

序合并可能会失策。

当连接条件是在两个表之间使用不等式(如<、<=、>、>=)时,排序合并连接很有用。排序

合并连接执行比对大量数据进行嵌套循环连接更好(不要用HASH 连接,除非有等价条件)。

在合并连接里,没有驱动表概念,该连接主要考虑两步:

1. 排序连接操作:连接键的输入端都是被排序过;

2. 合并连接操作:排序列表要合并在一起。

例子:带有非等价的排序连接

SELECT SUM(l.), l2.

FROM order_items l, order_items l2

WHERE l. < l2.

AND l.order_id <> l2.order_id

GROUP BY l2., l2.line_item_id ;

Plan

--------------------------------------------------

SELECT STATEMENT

SORT GROUP BY

MERGE JOIN

SORT JOIN

TABLE ACCESS FULL ORDER_ITEMS

FILTER

SORT JOIN

TABLE ACCESS FULL ORDER_ITEMS

时间: 2024-10-02 18:57:03

优化器的相关文章

ORACLE优化器RBO与CBO介绍总结

RBO和CBO的基本概念   Oracle数据库中的优化器又叫查询优化器(Query Optimizer).它是SQL分析和执行的优化工具,它负责生成.制定SQL的执行计划.Oracle的优化器有两种,基于规则的优化器(RBO)与基于代价的优化器(CBO)          RBO: Rule-Based Optimization 基于规则的优化器          CBO: Cost-Based Optimization 基于代价的优化器 RBO 自ORACLE 6以来被采用,一直沿用至ORA

为什么基于代价的优化器做出错误选择

基于代价的优化器(CBO)在进行全表扫描时偶尔会作出一些错误的选择,这种情况尤其发生在Oracle7和Oracle8之中.有几种情况会导致这个问题,分别如下所示:最高使用标记(High water mark)太高:当要在一个表中进行大量的删除时,最高使用标记可能会远远高于实际用到的数据块(block)数量.因此,如果依赖于最高使用标记,CBO常常会错误的调用全表扫描. 错误的优化模式:如果OPTIMIZER_MODE被设置为ALL_ROWS或者CHOOSE,那么SQL优化器会更乐于使用全表扫描.

Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.1

oracle|优化 Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.1        如果在Oracle以前的版本(7.0或更早)中开发应用程序,数据库会采用基于规则的优化器(译者注:以下称RBO),本篇将帮助你理解Oracle优化器并迁移到基于成本优化器(译者注:以下称CBO)的几种高效方法.下面是五大部分的第一部分   第一部分 1.         什么是优化器? 2.         为什么要优化? 3.         可用的优化器. 4.        

sql优化器探讨

优化 多年以来,商业数据库生产商一直致力于提高数据库的查询性能.尽管他们持续地付出努力和辛勤地工作,我们还是无法看到关系型数据库系统(rdbms)在性能上有显著的提高.用户继续忍受性能低下的sql语句,数据库专家们继续在sql语句优化的泥潭中痛苦挣扎. 本文将介绍数据库查询优化器是如何工作的.为什么问题持续存在,并深入探讨数据库查询优化器将来的发展方向. 数据库查询优化器 数据库查询优化器是rdbms服务器的一个组成部分.对于基于成本的优化,数据库查询优化器的任务是,通过产生可供选择的执行计划,

ORACLE优化器

oracle|优化 ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性) 设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖. 为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令

说一说Oracle的优化器(Optimizer)

oracle|优化 本文的目的:1.说一说Oracle的Optimizer及其相关的一些知识.2.回答一下为什么有时一个表的某个字段明明有索引,当观察一些SQL的执行计划时,发现确不走索引的问题.3.如果你对 FIRST_ROWS. ALL_ROWS这两种模式有疑惑时也可以看一下这篇文章. 开始吧: Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执行计划去执行.分析语句的执行计划的工作是由优化器(Optimizer)来完成的.不同的情况,一条SQL可能有多种执行计划,但

Oracle Optimizer:迁移到使用基于成本的优化器-----系列2.1

oracle|优化 Oracle Optimizer:迁移到使用基于成本的优化器-----系列2.1   系列之二包含影响优化器选择执行计划的初始化参数和Oracle内部隐藏参数,合理设置这些参数对于优化器是相当重要的.        6.影响优化器的初始化参数        除了生成统计资料之外,下面提及的参数设置在你的系统正常工作中扮演着极重要的角色.这些设置将大多依赖于你想创建何种类型的环境.联机,批处理,数据仓库或多于一个的组合.请注意优化器考虑这些参数以评估每一个在CBO生成的执行计划

Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.2

oracle|优化 Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.2 3.2基于成本的优化器(CBO) 基于成本优化器遵循计算代价的方法学.所有的执行计划随成本标识,优化器选择成本最低的一个.在执行计划中,较高的成本将意味着较高的资源.成本越低,对查询来说越高效.CBO使用所有存储在数据字典中可用的统计资料信息和柱状图,用户提供提示和的参数设置来达成使用的成本,CBO生成所有可能访问方法的排列然后选择最合适的.排列的数量依赖于查询中出现的表数量,有时能达到约80,

Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.3

oracle|优化 Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.3   3.2.3     可用CBO模式 CBO有两种运行模式:ALL_ROWS和FIRST_ROWS. FIRST_ROWS的目标是尽可能最快的返回行.这种模式告诉优化器响应时间是最重要的.它偏好嵌套连接方式. FIRST_ROWS也以考虑成本为主要规则来处理行.通常规则是使用索引的计划而不是使用全表扫描的计划作为访问路径,ORDER BY子句导致索引访问,等等 从9i版本起,在First提示中

Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.4

oracle|优化 Oracle Optimizer:迁移到使用基于成本的优化器-----系列1.4 3.2.3最低要求     用CBO的最低要求是设置优化器模式为FRIST_ROWS或者ALL_ROWS(或CHOOSE)并为对象生成统计资料.然而,这并不能保证你的系统能工作到最佳状态.参照第二部分(初始化参数)涉及初始化参数的信息.     不管是否设置优化器模式.如果有以下情况之一,CBO将会自动调用:      1.用到提示.     2.用到分区表.     3.设置并行表 3.2.4