
2
基于成本的
Oracle
优化法则
1.1 优化器选项
最常见的 SQL 语句类型是 select 语句—— 虽然本书的其他部分都将集中讨论 select 语
句,但此处需要强调的是,无论是哪种语句,只要是执行查询操作,DML(比如更新)或
DDL(比如索引重建)都需要通过基于成本的优化器(CBO)进行分析。
Oracle 为基于成本的优化器提供了 3 个变体。这 3 个变体的代码中构建不同的约束,
但是它们都遵循同一策略—— 即针对某个 SQL 语句,寻找能够最少的资源消耗来达到目标
的执行机制。这 3 个变体可以通过参数 optimizer_mode 标识:
● all_rows:优化器将寻找能够在最短的时间内完成语句的执行计划(通常表示“返回
所有行”)。该变体没有在代码中构建特别的约束。
● first_rows_N:N 可以为 1、10、100 或 1000(如果需要进行进一步优化,可以采用
first_rows(n)提示的形式,其中 n 可以是任意正整数)。优化器首先通过彻底分析第
一个连接顺序(join order)来估计返回行的总数目。这亲就可以知道查询可能获得的
整个数据集的片断,并重新启动整个优化进程,其目标在于找到能够以最小的资
源消耗返回整个数据片断的执行计划。该选项是在 Oracle 9i 中引入的。
● first_rows:在 Oracle 9i 中这一选项已经过时,但是出于向后兼容的原因,仍然保
留了这一选项。该选项的作用在于寻找能够在最短的时间内返回结果集的第一行
的执行计划。该变体的代码中构建了几个高层次约束。例如,有一个约束就是“避
免归并连接和散列连接,除非除此以外只能对内部(第二个)表进行全表扫描的嵌套
循环”。这一规则倾向于促使优化器使用索引访问路径,偶尔会出现非常不恰当
的访问路径。针对这一特殊问题的示例和相关内容可以在本章的联机代码包中的
脚本文件 first_rows.sql 中找到,从 Apress 网站(www.apress.com) 和
www.tupwk.com.cn 中都可以找到这个代码包。
参数 optimizer_mode 还存在其他两个选项(
即使在 Oracle 10g 中也是如此),分别为 rule
和 choose。由于基于规则的优化(Rule Based Optimization)在多年前就已过时(只有某些内部
SQL 仍在使用/*+ rule */提示),而且 Oracle 10g 中最终不再支持 RBO,所以本书将完全忽
略 RBO。
对于 choose 模式来说,它为优化器提供了一种运行时选择方式,可以在基于规则的优
化和 all_rows 之间进行选择。既然本书忽略基于规则的优化,那么 choose 模式就无需多言
了。在此仅仅申明以下问题,在 Oracle 10g 中,如果使用数据库配置助手(Database
Configuration Assistant,DBCA)来建立数据库,或者通过调用脚本 catproc.sql 来手动创建数
据库,那么将自动安装一个作业(由脚本 catmwin.sql 创建,在视图 dba_scheduler_jobs 中可
见),它将对缺少统计信息或统计信息失效的任何表每 24 小时生成一次统计信息。因此,
如果将 optimizer_mode 设置为 choose,可能将触发 all_rows 优化,但是您可能会发现所有
缺少最新统计信息的表将采用动态采样。这是因为在 Oracle 10g 中,参数
optimizer_dynamic_sampling 的默认值为 2(意味着针对没有统计信息的任何表都采用动态
采样),而在 Oracle 9i 中该参数的默认值为 1。
另一个与 optimizer_mode 有关的参数为 optimizer_goal。虽然 optimizer_goal 只能在会
话中动态地设定,而且在 spfile(init.ora)中不可用,但是就优化策略而言,这两个参数似乎
评论